Projetar o gráfico de navegação

O componente de navegação usa um gráfico de navegação para gerenciar a navegação do app. O gráfico de navegação é uma estrutura de dados que contém cada destino no seu app e as conexões entre eles.

Tipos de destino

Existem três tipos gerais de destinos: hospedado, diálogo e atividade. A tabela abaixo descreve esses três tipos de destino e as finalidades deles.

Tipo

Descrição

Casos de uso

Hospedado

Preenche todo o host de navegação. Ou seja, o tamanho de um destino hospedado é o mesmo do host de navegação, e os destinos anteriores não são visíveis.

Telas principal e de detalhes.

Caixa de diálogo

Apresenta componentes de interface de sobreposição. Essa interface não está vinculada ao local nem ao tamanho do host de navegação. Os destinos anteriores ficam visíveis abaixo dele.

Alertas, seleções, formulários

Atividade

Representa telas ou recursos únicos no app.

Servem como um ponto de saída para o gráfico de navegação que inicia uma nova atividade do Android gerenciada separadamente do componente Navigation.

No desenvolvimento moderno para Android, um app consiste em uma única atividade. Portanto, os destinos de atividade são mais indicados para interação com atividades de terceiros ou como parte do processo de migração.

Este documento contém exemplos de destinos hospedados, que são os destinos mais comuns e fundamentais. Consulte os guias abaixo para mais informações sobre outros destinos:

Estruturas de trabalho

Embora o mesmo fluxo de trabalho geral se aplique a todos os casos, a maneira exata de criar um host e um gráfico de navegação depende do framework de IU que você usa.

  • Compose:use o elemento combinável NavHost. Crie um NavGraph para ele usando a DSL de Kotlin (link em inglês). É possível criar o gráfico de duas maneiras:
    • Como parte do NavHost:construa o gráfico de navegação diretamente como parte da adição do NavHost.
    • De forma programática:use o método NavController.createGraph() para criar um NavGraph e transmiti-lo diretamente para NavHost.
  • Fragmentos:ao usar fragmentos com o framework de interface de visualizações, use um NavHostFragment como host. Há várias maneiras de criar um gráfico de navegação:
    • De forma programática:use a DSL do Kotlin para criar um NavGraph e aplicá-lo diretamente ao NavHostFragment.
      • A função createGraph() usada com a DSL do Kotlin para fragmentos e Compose é a mesma.
    • XML:programe o host e o gráfico de navegação diretamente em XML.
    • Editor do Android Studio:use o editor de GUI no Android Studio para criar e ajustar seu gráfico como um arquivo de recurso XML.

Compose

No Compose, use o elemento combinável NavHost para criar o gráfico de navegação. Veja o exemplo a seguir:

val navController = rememberNavController()

NavHost(navController = navController, startDestination = "profile") {
    composable("profile") { Profile( /* ... */ ) }
    composable("friendslist") { FriendsList( /* ... */ ) }
    // Add more destinations similarly.
}
  1. A chamada para o elemento combinável NavHost transmite uma string NavController e uma route que correspondem ao destino inicial.
  2. A lambda transmitida ao NavHost chama NavController.creatGraph() e retorna um NavGraph.
  3. As chamadas para NavGraphBuilder.composable() adicionam destinos aos NavGraph resultantes.
  4. Nesse caso, os destinos são os elementos combináveis Profile e FriendsList. As strings de rota "profile" e "friendslist" se tornam as chaves que identificam os dois destinos.

Para entender melhor a lambda que cria o NavGraph, considere que, para criar o mesmo gráfico do snippet anterior, você poderia criar o NavGraph separadamente usando NavController.createGraph() e transmiti-lo diretamente ao NavHost:

val navGraph by remember(navController) {
  navController.createGraph(startDestination = "profile") {
    composable("profile") { Profile() }
    composable("friendslist") { FriendsList() }
  }
}
NavHost(navController, navGraph)

Exemplo mínimo

Um exemplo mínimo, mas completo, de uma NavController e uma NavHost trabalhando juntas:

// Define the Profile composable.
@Composable
fun Profile(onNavigateToFriendsList: () -> Unit) {
  Text("Profile")
  Button(onClick = { onNavigateToFriendsList() }) {
    Text("Go to Friends List")
  }
}

// Define the FriendsList composable.
@Composable
fun FriendsList(onNavigateToProfile: () -> Unit) {
  Text("Friends List")
  Button(onClick = { onNavigateToProfile() }) {
    Text("Go to Profile")
  }
}

// Define the MyApp composable, including the `NavController` and `NavHost`.
@Composable
fun MyApp() {
  val navController = rememberNavController()
  NavHost(navController, startDestination = "profile") {
    composable("profile") { Profile(onNavigateToFriendsList = { navController.navigate("friendslist") }) }
    composable("friendslist") { FriendsList(onNavigateToProfile = { navController.navigate("profile") }) }
  }
}

Como demonstrado no snippet, em vez de transmitir o NavController para os elementos combináveis, exponha um evento para o NavHost. Ou seja, os elementos combináveis precisam ter um parâmetro do tipo () -> Unit para o qual o NavHost transmite uma lambda que chama NavController.navigate().

Fragments

Conforme descrito nas seções anteriores, ao usar fragmentos, você tem a opção de criar um gráfico de navegação de forma programática usando a DSL do Kotlin, o XML ou o editor do Android Studio.

As seções a seguir detalham essas diferentes abordagens.

De maneira programática

A DSL do Kotlin oferece uma maneira programática de criar um gráfico de navegação com fragmentos. De muitas maneiras, isso é mais limpo e mais moderno do que usar um arquivo de recurso XML.

Confira o exemplo abaixo, que implementa um gráfico de navegação em duas telas.

Primeiro, é necessário criar a NavHostFragment, que não pode incluir um elemento app:navGraph:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

Em seguida, transmita o id do NavHostFragment para NavController.findNavController(). Isso associa o NavController ao NavHostFragment.

Em seguida, a chamada para NavController.createGraph() vincula o gráfico ao NavController e, consequentemente, também ao NavHostFragment:

// Retrieve the NavController.
val navController = findNavController(R.id.nav_host_fragment)

// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = "profile"
) {
    // Associate each destination with one of the route constants.
    fragment<ProfileFragment>("profile") {
        label = "Profile"
    }

    fragment<FriendsListFragment>("friendsList") {
        label = "Friends List"
    }

    // Add other fragment destinations similarly.
}

O uso da DSL dessa maneira é muito semelhante ao fluxo de trabalho descrito na seção anterior no Compose. Por exemplo, aqui e aqui, a função NavController.createGraph() gera o NavGraph. Da mesma forma, enquanto NavGraphBuilder.composable() adiciona destinos combináveis ao gráfico, aqui NavGraphBuilder.fragment() adiciona um destino de fragmento.

Para saber mais sobre como usar a DSL do Kotlin, consulte Criar um gráfico com a DSL do NavGraphBuilder.

XML

Você pode criar o XML diretamente. O exemplo a seguir espelha e é equivalente ao exemplo de duas telas da seção anterior.

Primeiro, crie um NavHostFragment. Ele serve como o host de navegação, que contém o gráfico de navegação real.

Uma implementação mínima de um NavHostFragment:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph" />

</FrameLayout>

O NavHostFragment contém o atributo app:navGraph. Use esse atributo para conectar seu gráfico de navegação ao host de navegação. Confira abaixo um exemplo de como implementar o gráfico:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/profile">

    <fragment
        android:id="@+id/profile"
        android:name="com.example.ProfileFragment"
        android:label="Profile">

        <!-- Action to navigate from Profile to Friends List. -->
        <action
            android:id="@+id/action_profile_to_friendslist"
            app:destination="@id/friendslist" />
    </fragment>

    <fragment
        android:id="@+id/friendslist"
        android:name="com.example.FriendsListFragment"
        android:label="Friends List" />

    <!-- Add other fragment destinations similarly. -->
</navigation>

Você usa ações para definir as conexões entre destinos diferentes. Neste exemplo, o fragmento profile contém uma ação que navega para friendslist. Para saber mais, consulte Usar ações e fragmentos de navegação.

Editor

Você pode gerenciar o gráfico de navegação do seu app usando o Navigation Editor no Android Studio. Essencialmente, essa é uma GUI que pode ser usada para criar e editar o XML do NavigationFragment, conforme mostrado na seção anterior.

Para mais informações, consulte o Navigation Editor.

Gráficos aninhados

Também é possível usar gráficos aninhados. Isso envolve o uso de um gráfico como destino de navegação. Para mais informações, consulte Gráficos aninhados.

Leitura adicional

Para mais conceitos principais de navegação, consulte os guias a seguir: