Cómo diseñar tu gráfico de navegación

El componente de Navigation utiliza un gráfico de navegación para administrar este aspecto de tu app. El gráfico de navegación es una estructura de datos que contiene cada destino dentro de tu app y las conexiones entre ellos.

Tipos de destino

Existen tres tipos generales de destinos: alojados, diálogos y actividades. En la siguiente tabla, se describen estos tres tipos de destino y sus propósitos.

Tipo

Descripción

Casos de uso

Alojada

Llena todo el host de navegación. Es decir, el tamaño de un destino alojado es el mismo que el tamaño del host de navegación, y los destinos anteriores no son visibles.

Pantallas principales y de detalles

Diálogo

Presenta componentes superpuestos de la IU. Esta IU no está vinculada a la ubicación del host de navegación ni a su tamaño. Los destinos anteriores se pueden ver debajo del destino.

Alertas, selecciones y formularios.

Actividad

Representa pantallas o funciones únicas dentro de la app.

Sirve como punto de salida al gráfico de navegación que inicia una nueva actividad de Android que se administra de forma independiente del componente Navigation.

En Modern Android Development, una app consta de una sola actividad. Por lo tanto, es mejor usar los destinos de actividad cuando se interactúa con actividades de terceros o como parte del proceso de migración.

Este documento contiene ejemplos de destinos alojados, que son los destinos más comunes y fundamentales. Consulta las siguientes guías para obtener información sobre los otros destinos:

Frameworks

Aunque en todos los casos se aplica el mismo flujo de trabajo general, la forma exacta de crear un host de navegación y un gráfico depende del framework de IU que uses.

  • Compose: Usa el elemento NavHost componible. Crea un NavGraph con el DSL de Kotlin. Puedes crear el gráfico de dos maneras:
    • Como parte de NavHost: Construye el gráfico de navegación directamente como parte de la adición de NavHost.
    • De manera programática: usa el método NavController.createGraph() para crear un NavGraph y pasarlo directamente a NavHost.
  • Fragmentos: Cuando uses fragmentos con el framework de IU de vistas, usa un NavHostFragment como host. Hay varias formas de crear un gráfico de navegación:
    • De manera programática: Usa el DSL de Kotlin para crear un NavGraph y aplicarlo directamente en NavHostFragment.
      • La función createGraph() que se usa con la DSL de Kotlin para fragmentos y Compose es la misma.
    • XML: Escribe el host de navegación y el gráfico directamente en XML.
    • Editor de Android Studio: Usa el editor de GUI de Android Studio para crear y ajustar tu gráfico como un archivo de recursos XML.

Redactar

En Compose, usa el elemento componible NavHost para crear tu gráfico de navegación. Consulta el siguiente ejemplo:

val navController = rememberNavController()

NavHost(navController = navController, startDestination = "profile") {
    composable("profile") { Profile( /* ... */ ) }
    composable("friendslist") { FriendsList( /* ... */ ) }
    // Add more destinations similarly.
}
  1. La llamada al elemento componible NavHost pasa una cadena NavController y una route que corresponde al destino de inicio.
  2. La lambda pasada a NavHost finalmente llama a NavController.creatGraph() y muestra un NavGraph.
  3. Las llamadas a NavGraphBuilder.composable() agregan destinos al NavGraph resultante.
  4. En este caso, los destinos son los elementos componibles Profile y FriendsList. Las cadenas de ruta "profile" y "friendslist" se convierten en las claves que identifican los dos destinos.

Para comprender mejor la expresión lambda que crea el NavGraph, ten en cuenta que, para compilar el mismo gráfico que en el fragmento anterior, puedes crear el NavGraph por separado usando NavController.createGraph() y pasarlo directamente al NavHost:

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

Ejemplo mínimo

Un ejemplo mínimo pero completo de NavController y NavHost que funcionan juntos:

// 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 se muestra en el fragmento, en lugar de pasar NavController a los elementos componibles, expone un evento a NavHost. Es decir, los elementos componibles deben tener un parámetro de tipo () -> Unit para el cual NavHost pase una expresión lambda que llame a NavController.navigate().

Fragmentos

Como se describe en las secciones anteriores, cuando usas fragmentos, tienes la opción de crear un gráfico de navegación de manera programática con el DSL, XML o el editor de Android Studio de Kotlin.

En las siguientes secciones, se detallan estos enfoques diferentes.

De manera programática

El DSL de Kotlin proporciona una manera programática de crear un gráfico de navegación con fragmentos. En muchos aspectos, esto es más prolijo y moderno que usar un archivo de recursos XML.

Considera el siguiente ejemplo, que implementa un gráfico de navegación de dos pantallas.

En primer lugar, es necesario crear el NavHostFragment, que no debe incluir un 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>

A continuación, pasa el elemento id de NavHostFragment a NavController.findNavController(). De esta manera, se asocia el NavController con el NavHostFragment.

Luego, la llamada a NavController.createGraph() vincula el gráfico a NavController y, por lo tanto, también a 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.
}

Usar el DSL de esta manera es muy similar al flujo de trabajo descrito en la sección anterior de Compose. Por ejemplo, tanto allí como aquí, la función NavController.createGraph() genera el NavGraph. Del mismo modo, mientras que NavGraphBuilder.composable() agrega destinos componibles al gráfico, aquí NavGraphBuilder.fragment() agrega un destino de fragmento.

Si deseas obtener más información para usar la DSL de Kotlin, consulta Cómo compilar un gráfico con el DSL de NavGraphBuilder.

XML

Puedes escribir directamente el XML tú mismo. El siguiente ejemplo se duplica y es equivalente al ejemplo de dos pantallas de la sección anterior.

Primero, crea un NavHostFragment. Esto funciona como el host de navegación que contiene el gráfico de navegación real.

Una implementación mínima de un 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>

NavHostFragment contiene el atributo app:navGraph. Usa este atributo para conectar tu gráfico de navegación al host de navegación. A continuación, se muestra un ejemplo de cómo puedes implementar el grafo:

<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>

Usas acciones para definir las conexiones entre los diferentes destinos. En este ejemplo, el fragmento profile contiene una acción que navega a friendslist. Para obtener más información, consulta Cómo usar fragmentos y acciones de Navigation.

Editor

Puedes administrar el gráfico de navegación de tu app con el editor de navegación de Android Studio. En esencia, es una GUI que puedes usar para crear y editar tu XML NavigationFragment, como se ve en la sección anterior.

Para obtener más información, consulta Editor de navegación.

Gráficos anidados

También puedes usar gráficos anidados. Esto implica usar un gráfico como destino de navegación. Para obtener más información, consulta Gráficos anidados.

Lectura adicional

Para conocer más conceptos básicos de navegación, consulta las siguientes guías: