El componente Navigation utiliza un gráfico de navegación para administrar la navegación 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 destinos
Existen tres tipos generales de destinos: alojados, de diálogo y de actividad. En la siguiente tabla, se describen estos tres tipos de destinos y sus propósitos.
Tipo |
Descripción |
Casos de uso |
---|---|---|
Alojado |
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 |
De 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 |
De 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 externas o como parte del proceso de migración. |
En este documento, se incluyen 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 y un gráfico de navegación depende del framework de IU que uses.
- Compose: usa el elemento componible
NavHost
. Agrega unNavGraph
con el DSL de Kotlin. Puedes crear el gráfico de dos maneras:- Como parte del NavHost: construye el gráfico de navegación directamente como parte de agregar el
NavHost
. - De manera programática: usa el método
NavController.createGraph()
para crear unNavGraph
y pasarlo directamente alNavHost
.
- Como parte del NavHost: construye el gráfico de navegación directamente como parte de agregar el
- Fragmentos: Cuando uses fragmentos con el framework de IU de vistas, usa un
NavHostFragment
como host. Existen 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 elNavHostFragment
.- La función
createGraph()
que se usa con el DSL de Kotlin para fragmentos y Compose es la misma.
- La función
- XML: escribe el host y el gráfico de navegación 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.
- De manera programática: usa el DSL de Kotlin para crear un
Compose
En Compose, usa un objeto o una clase serializable para definir una ruta. Una ruta describe cómo llegar a un destino y contiene toda la información que este requiere.
Usa la anotación @Serializable
para crear automáticamente los métodos de serialización y deserialización necesarios para tus tipos de ruta. El complemento de serialización de Kotlin proporciona esta anotación. Sigue estas instrucciones para agregar este complemento.
Una vez que hayas definido tus rutas, usa el elemento componible NavHost
para crear tu gráfico de navegación. Consulta el siguiente ejemplo:
@Serializable
object Profile
@Serializable
object FriendsList
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Profile) {
composable<Profile> { ProfileScreen( /* ... */ ) }
composable<FriendsList> { FriendsListScreen( /* ... */ ) }
// Add more destinations similarly.
}
- Un objeto serializable representa cada una de las dos rutas,
Profile
yFriendsList
. - La llamada al elemento componible
NavHost
pasa unNavController
y una ruta para el destino de inicio. - La expresión lambda pasada al
NavHost
finalmente llama aNavController.createGraph()
y muestra unNavGraph
. - Cada ruta se proporciona como argumento de tipo a
NavGraphBuilder.composable<T>()
, que agrega el destino alNavGraph
resultante. - La lambda que se pasa a
composable
es lo queNavHost
muestra para ese destino.
Comprende la lambda
Para comprender mejor la expresión lambda que crea el NavGraph
, considera que, para compilar el mismo gráfico que en el fragmento anterior, puedes crear el NavGraph
por separado con NavController.createGraph()
y pasarlo al NavHost
directamente:
val navGraph by remember(navController) {
navController.createGraph(startDestination = Profile)) {
composable<Profile> { ProfileScreen( /* ... */ ) }
composable<FriendsList> { FriendsListScreen( /* ... */ ) }
}
}
NavHost(navController, navGraph)
Pasa argumentos
Si necesitas pasar datos a un destino, define la ruta con una clase que
tenga parámetros. Por ejemplo, la ruta Profile
es una clase de datos con un parámetro name
.
@Serializable
data class Profile(val name: String)
Cada vez que necesites pasar argumentos a ese destino, creas una instancia de tu clase de ruta y pasas los argumentos al constructor de la clase.
Para los argumentos opcionales, crea campos anulables con un valor predeterminado.
@Serializable
data class Profile(val nickname: String? = null)
Obtén la instancia de ruta
Puedes obtener la instancia de ruta con NavBackStackEntry.toRoute()
o SavedStateHandle.toRoute()
. Cuando creas un destino con composable()
, NavBackStackEntry
está disponible como parámetro.
@Serializable
data class Profile(val name: String)
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Profile(name="John Smith")) {
composable<Profile> { backStackEntry ->
val profile: Profile = backStackEntry.toRoute()
ProfileScreen(name = profile.name) }
}
Ten en cuenta lo siguiente en este fragmento:
- La ruta
Profile
especifica el destino de inicio en el gráfico de navegación, con"John Smith"
como argumento paraname
. - El destino en sí es el bloque
composable<Profile>{}
. - El elemento componible
ProfileScreen
toma el valor deprofile.name
para su propio argumentoname
. - Por lo tanto, el valor
"John Smith"
pasa aProfileScreen
.
Ejemplo mínimo
Un ejemplo completo de NavController
y NavHost
que funcionan juntos:
@Serializable
data class Profile(val name: String)
@Serializable
object FriendsList
// Define the ProfileScreen composable.
@Composable
fun ProfileScreen(
profile: Profile
onNavigateToFriendsList: () -> Unit,
) {
Text("Profile for ${profile.name}")
Button(onClick = { onNavigateToFriendsList() }) {
Text("Go to Friends List")
}
}
// Define the FriendsListScreen composable.
@Composable
fun FriendsListScreen(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(name = "John Smith")) {
composable<Profile> { backStackEntry ->
val profile: Profile = backStackEntry.toRoute()
ProfileScreen(
profile = profile,
onNavigateToFriendsList = {
navController.navigate(route = FriendsList)
}
)
}
composable<FriendsList> {
FriendsListScreen(
onNavigateToProfile = {
navController.navigate(
route = Profile(name = "Aisha Devi")
)
}
)
}
}
}
Como se muestra en el fragmento, en lugar de pasar el NavController
a los elementos componibles, expone un evento al NavHost
. Es decir, los elementos componibles deben tener un parámetro de tipo () -> Unit
para el cual el 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 de Kotlin, XML o el editor de Android Studio.
En las siguientes secciones, se detallan estos diferentes enfoques.
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 sentidos, esto es más prolijo y moderno que usar un archivo de recursos XML.
Ten en cuenta 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 id
del NavHostFragment
a NavController.findNavController
. De esta manera, se asocia el NavController con el NavHostFragment
.
Luego, la llamada a NavController.createGraph()
vincula el gráfico al NavController
y, por lo tanto, también al NavHostFragment
:
@Serializable
data class Profile(val name: String)
@Serializable
object FriendsList
// 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(name = "John Smith")
) {
// 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 sobre 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.
Para obtener más información sobre cómo usar el DSL de Kotlin, consulta Cómo compilar un gráfico con el DSL de NavGraphBuilder.
XML
Puedes escribir directamente el XML por tu cuenta. El siguiente ejemplo replica el ejemplo de dos pantallas de la sección anterior y es equivalente a él.
Primero, crea un NavHostFragment
. Esto sirve como el host de navegación que contiene el gráfico de navegación real.
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>
El 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 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>
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 acciones y fragmentos de Navigation.
Editor
Puedes administrar el gráfico de navegación de tu app con el Editor de Navigation en Android Studio. En esencia, es una GUI que puedes usar para crear y editar tu XML de NavigationFragment
, como se muestra en la sección anterior.
Para obtener más información, consulta Editor de Navigation.
Gráficos anidados
También puedes usar gráficos anidados. Eso implica usar un gráfico como destino de navegación. Para obtener más información, consulta Gráficos anidados.
Lecturas adicionales
Para conocer más conceptos básicos de navegación, consulta las siguientes guías:
- Descripción general: Asegúrate de leer la descripción general del componente Navigation
- Destinos de actividad: Ejemplos de cómo implementar destinos que llevan al usuario a las actividades
- Destinos de diálogo: Ejemplos de cómo crear destinos que llevan al usuario a un diálogo
- Cómo navegar a un destino: Una guía detallada en la que se explica cómo navegar de un destino a otro
- Gráficos anidados: Una guía detallada sobre cómo anidar un gráfico de navegación dentro de otro