La navigation vers une destination est effectuée à l'aide d'un objet NavController
, qui gère la navigation dans l'application via un NavHost
. Chaque NavHost
a son propre NavController
correspondant. NavController
propose plusieurs façons d'accéder à une destination, qui sont décrites plus en détail dans les sections ci-dessous.
Afin de récupérer NavController
pour un fragment, une activité ou une vue, utilisez l'une des méthodes suivantes :
Kotlin
Java
NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, @IdRes int viewId)
Navigation.findNavController(View)
Après avoir récupéré un NavController
, vous pouvez appeler l'une des surcharges de navigate()
pour naviguer entre les destinations. Chaque surcharge est compatible avec divers scénarios de navigation, comme décrit dans les sections suivantes.
Utiliser Safe Args pour naviguer de manière sécurisée
Pour naviguer entre les destinations, nous vous recommandons d'utiliser le plug-in Gradle Safe Args. Ce plug-in génère des classes d'objets et de compilateurs simples qui permettent une navigation sécurisée entre les destinations. Safe Args est recommandé à la fois pour la navigation et la transmission de données entre des destinations.
Pour ajouter Safe Args à votre projet, incluez le classpath
suivant dans votre fichier build.gradle
de premier niveau :
Groovy
buildscript { repositories { google() } dependencies { def nav_version = "2.5.3" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } }
Kotlin
buildscript { repositories { google() } dependencies { val nav_version = "2.5.3" classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version") } }
Vous devez également appliquer l'un des deux plug-ins disponibles.
Pour générer un code en langage Java adapté aux modules en Java ou mixant du Java et du Kotlin, ajoutez la ligne suivante au fichier build.gradle
de votre application ou module :
Groovy
plugins { id 'androidx.navigation.safeargs' }
Kotlin
plugins { id("androidx.navigation.safeargs") }
Sinon, pour générer un code Kotlin adapté aux modules exclusivement en Kotlin, ajoutez la ligne suivante :
Groovy
plugins { id 'androidx.navigation.safeargs.kotlin' }
Kotlin
plugins { id("androidx.navigation.safeargs.kotlin") }
android.useAndroidX=true
doit figurer dans votre fichier gradle.properties
, tel qu'indiqué sur la page Migrer vers AndroidX.
Une fois que vous avez activé Safe Args, votre code généré contient des classes et des méthodes pour chaque action que vous avez définie, ainsi que des classes correspondant à chaque destination d'envoi et de réception.
Safe Args génère une classe pour chaque destination à l'origine d'une action. Le nom de classe généré ajoute "Directions" au nom de la classe de destination à l'origine de l'action. Par exemple, si la destination à l'origine de l'action est SpecifyAmountFragment
, la classe générée est nommée SpecifyAmountFragmentDirections
.
La classe générée contient une méthode statique pour chaque action définie dans la destination à l'origine de l'action. Cette méthode accepte tous les paramètres d'action définis comme arguments et renvoie un objet NavDirections
que vous pouvez transmettre directement à navigate()
.
Exemple Safe Args
Supposons que nous ayons un graphe de navigation avec une seule action qui relie deux destinations, SpecifyAmountFragment
et ConfirmationFragment
.
ConfirmationFragment
accepte un seul paramètre float
que vous fournissez dans le cadre de l'action.
Safe Args génère une classe SpecifyAmountFragmentDirections
avec une seule méthode, actionSpecifyAmountFragmentToConfirmationFragment()
, et une classe interne appelée ActionSpecifyAmountFragmentToConfirmationFragment
. La classe interne est dérivée de NavDirections
et stocke l'ID d'action associé et le paramètre float
. L'objet NavDirections
renvoyé peut ensuite être transmis directement à navigate()
, comme illustré dans l'exemple suivant :
Kotlin
override fun onClick(v: View) { val amount: Float = ... val action = SpecifyAmountFragmentDirections .actionSpecifyAmountFragmentToConfirmationFragment(amount) v.findNavController().navigate(action) }
Java
@Override public void onClick(View view) { float amount = ...; action = SpecifyAmountFragmentDirections .actionSpecifyAmountFragmentToConfirmationFragment(amount); Navigation.findNavController(view).navigate(action); }
Pour en savoir plus sur la transmission de données entre des destinations avec Safe Args, consultez la section Utiliser Safe Args pour transmettre des données en toute sécurité.
Naviguer à l'aide d'un ID
navigate(int)
accepte l'ID de ressource d'une action ou d'une destination. L'extrait de code suivant montre comment accéder à ViewTransactionsFragment
:
Kotlin
viewTransactionsButton.setOnClickListener { view -> view.findNavController().navigate(R.id.viewTransactionsAction) }
Java
viewTransactionsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Navigation.findNavController(view).navigate(R.id.viewTransactionsAction); } });
Pour les boutons, il existe trois variantes de Navigation.createNavigateOnClickListener()
.
Ces variantes sont utiles avec le langage de programmation Java. Si vous utilisez Kotlin, OnClickListener
est une interface SAM. Vous pouvez donc utiliser un lambda de fin. Cette approche peut être plus courte et plus facile à lire que d'appeler directement createNavigateOnClickListener()
.
Pour gérer d'autres composants d'interface utilisateur courants, tels que la barre d'application supérieure et la barre de navigation inférieure, consultez la section Mettre à jour les composants d'interface utilisateur avec NavigationUI.
Fournir des options de navigation aux actions
Lorsque vous définissez une action dans le graphe de navigation, le composant Navigation génère une classe NavAction
correspondante, qui contient les configurations définies pour cette action, y compris les suivantes :
- Destination : ID de ressource de la destination cible.
- Arguments par défaut :
android.os.Bundle
contenant les valeurs par défaut de la destination cible, le cas échéant. - Options de navigation : options de navigation représentées par
NavOptions
. Cette classe contient toutes les configurations spéciales permettant d'effectuer une transition vers et depuis la destination cible, y compris la configuration des ressources d'animation, le comportement de suppression de la pile et le lancement ou non de la destination en mode haut simple.
Examinons un exemple de graphe composé de deux écrans, accompagnés d'une action permettant de passer de l'un à l'autre :
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/a">
<fragment android:id="@+id/a"
android:name="com.example.myapplication.FragmentA"
android:label="a"
tools:layout="@layout/a">
<action android:id="@+id/action_a_to_b"
app:destination="@id/b"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"/>
</fragment>
<fragment android:id="@+id/b"
android:name="com.example.myapplication.FragmentB"
android:label="b"
tools:layout="@layout/b">
<action android:id="@+id/action_b_to_a"
app:destination="@id/a"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"/>
</fragment>
</navigation>
Lorsque le graphe de navigation est gonflé, ces actions sont analysées, et les objets NavAction
correspondants sont générés avec les configurations définies dans le graphe. Par exemple, action_b_to_a
est défini comme allant de la destination b
à la destination a
. L'action inclut des animations ainsi que le comportement popTo
qui supprime toutes les destinations de la pile "Retour". Tous ces paramètres sont enregistrés en tant que NavOptions
et sont associés à l'élément NavAction
.
Pour suivre cet élément NavAction
, utilisez NavController.navigate()
en transmettant l'ID de l'action, comme indiqué dans l'exemple suivant :
Kotlin
findNavController().navigate(R.id.action_b_to_a)
Java
NavigationHostFragment.findNavController(this).navigate(R.id.action_b_to_a);
Appliquer les options de navigation par programmation
Les exemples précédents montrent comment spécifier NavOptions
dans le fichier XML du graphe de navigation. Cependant, certaines options peuvent varier en fonction de contraintes inconnues au moment de la compilation. Dans ce cas, les options de navigation (NavOptions
) doivent être créées et définies de manière programmatique, comme indiqué dans l'exemple suivant :
Kotlin
findNavController().navigate( R.id.action_fragmentOne_to_fragmentTwo, null, navOptions { // Use the Kotlin DSL for building NavOptions anim { enter = android.R.animator.fade_in exit = android.R.animator.fade_out } } )
Java
NavController navController = NavHostFragment.findNavController(this); navController.navigate( R.id.action_fragmentOne_to_fragmentTwo, null, new NavOptions.Builder() .setEnterAnim(android.R.animator.fade_in) .setExitAnim(android.R.animator.fade_out) .build() );
Cet exemple utilise une forme étendue de navigate()
et contient des arguments Bundle
et NavOptions
supplémentaires. Toutes les variantes de navigate()
ont des versions étendues qui acceptent un argument NavOptions
.
Vous pouvez également appliquer NavOptions
de manière programmatique lorsque vous accédez à des liens profonds implicites :
Kotlin
findNavController().navigate( deepLinkUri, navOptions { // Use the Kotlin DSL for building NavOptions anim { enter = android.R.animator.fade_in exit = android.R.animator.fade_out } } )
Java
NavController navController = NavHostFragment.findNavController(this); navController.navigate( deepLinkUri, new NavOptions.Builder() .setEnterAnim(android.R.animator.fade_in) .setExitAnim(android.R.animator.fade_out) .build() );
Cette variante de navigate()
utilise un Uri
pour le lien profond implicite, ainsi que l'instance NavOptions
.
Naviguer à l'aide de DeepLinkRequest
navigate(NavDeepLinkRequest)
vous permet d'accéder directement à une destination implicite de lien profond, comme illustré dans l'exemple suivant :
Kotlin
val request = NavDeepLinkRequest.Builder .fromUri("android-app://androidx.navigation.app/profile".toUri()) .build() findNavController().navigate(request)
Java
NavDeepLinkRequest request = NavDeepLinkRequest.Builder .fromUri(Uri.parse("android-app://androidx.navigation.app/profile")) .build() NavHostFragment.findNavController(this).navigate(request)
En plus de l'Uri
, NavDeepLinkRequest
accepte également les liens profonds avec les actions et les types MIME. Pour ajouter une action à la requête, utilisez fromAction()
ou setAction()
.
Pour ajouter un type MIME à une requête, utilisez fromMimeType()
ou setMimeType()
.
Pour qu'une propriété NavDeepLinkRequest
soit correctement associé à une destination implicite de lien profond, l'URI, l'action et le type MIME doivent tous correspondre à l'élément NavDeepLink
dans la destination. Les URI doivent correspondre au modèle, les actions doivent être une correspondance exacte et les types MIME doivent être liés (par exemple, "image/jpg" correspond à "image/*").
Contrairement à la navigation à l'aide d'ID d'action ou de destination, vous pouvez accéder à n'importe quel lien profond de votre graphe, que la destination soit visible ou non. Vous pouvez accéder à une destination sur le graphe actuel ou sur un graphe complètement différent.
Lorsque vous utilisez NavDeepLinkRequest
, la pile "Retour" n'est pas réinitialisée. Ce comportement est différent de la navigation à l'aide de liens profonds, où la pile "Retour" est remplacée lors de la navigation. popUpTo
et popUpToInclusive
suppriment toujours les destinations de la pile "Retour", comme si vous aviez utilisé un ID.
Navigation et pile "Retour"
Android gère une pile "Retour" qui contient les destinations que vous avez consultées. La première destination de votre application est placée dans la pile lorsque l'utilisateur ouvre l'application. Chaque appel de la méthode navigate()
place une autre destination au-dessus de la pile. Appuyez sur Haut ou Retour pour appeler les méthodes NavController.navigateUp()
et NavController.popBackStack()
, respectivement, afin de supprimer la destination principale de la pile.
NavController.popBackStack()
renvoie une valeur booléenne indiquant s'il a bien renvoyé une autre destination. Le cas le plus courant d'affichage de la valeur false
est lorsque vous supprimez manuellement de la pile la destination de départ du graphe.
Lorsque la méthode renvoie false
, NavController.getCurrentDestination()
renvoie null
. Vous êtes responsable de la navigation vers une nouvelle destination ou de la gestion de la suppression de la pile en appelant finish()
au niveau de l'activité, comme illustré dans l'exemple suivant :
Kotlin
... if (!navController.popBackStack()) { // Call finish() on your Activity finish() }
Java
... if (!navController.popBackStack()) { // Call finish() on your Activity finish(); }
Les destinations de boîte de dialogue mettent en œuvre l'interface FloatingWindow
, ce qui indique qu'elles se superposent aux autres destinations sur la pile "Retour". Par conséquent, une ou plusieurs destinations FloatingWindow
ne peuvent être présentes qu'en haut de la pile "Retour" de navigation. Si vous accédez à une destination qui n'implémente pas FloatingWindow
, toutes les destinations FloatingWindow
sont automatiquement supprimées du haut de la pile. Cette approche garantit que la destination actuelle est toujours entièrement visible par rapport aux autres destinations de la pile "Retour".
Par exemple, si la pile "Retour" comporte uniquement des destinations non flottantes et que l'utilisateur accède à une destination Dialog
, elle peut se présenter comme illustré dans la figure 1 :

Dialog
en hautSi l'utilisateur accède ensuite à une autre destination Dialog
, celle-ci est ajoutée en haut de la pile "Retour", comme illustré dans la figure 2 :

Dialog
en hautSi l'utilisateur accède ensuite à une destination non flottante, toutes les destinations FloatingWindow
sont d'abord supprimées du haut de la pile "Retour" avant d'atteindre la nouvelle destination, comme illustré dans la figure 3 :

Dialog
sont supprimées de la pile, et la nouvelle destination est ajoutéepopUpTo et popUpToInclusive
Lorsque vous utilisez une action, vous pouvez éventuellement supprimer des destinations supplémentaires de la pile "Retour". Par exemple, si votre application implique un processus d'authentification initial, une fois qu'un utilisateur s'est connecté, vous devez supprimer toutes les destinations liées à l'authentification de la pile "Retour" afin que le bouton "Retour" ne redirige pas les utilisateurs vers ce processus.
Pour afficher des destinations lorsque vous passez d'une destination à une autre, ajoutez un attribut app:popUpTo
à l'élément <action>
associé. app:popUpTo
indique à la bibliothèque Navigation de supprimer certaines destinations de la pile "Retour" dans le cadre de l'appel de navigate()
. La valeur de l'attribut est l'ID de la destination la plus récente qui doit rester dans la pile.
Vous pouvez également inclure app:popUpToInclusive="true"
pour indiquer que la destination spécifiée dans app:popUpTo
doit également être supprimée de la pile "Retour".
Exemple avec popUpTo : logique circulaire
Imaginons que votre application comporte trois destinations (A, B et C), ainsi que des actions menant de A à B, de B à C et de C à A. Le graphe de navigation correspondant est illustré à la figure 4 :
Figure 4. Graphe de navigation circulaire avec trois destinations : A, B et C
À chaque action de navigation, une destination est ajoutée à la pile "Retour". Si vous répétiez ce processus, la pile "Retour" contiendrait plusieurs ensembles de chaque destination (A, B, C, A, B, C, A, etc.).
Pour éviter cette répétition, vous pouvez spécifier app:popUpTo
et app:popUpToInclusive
dans l'action qui vous emmène de la destination C à la destination A, comme illustré dans l'exemple suivant :
<fragment android:id="@+id/c" android:name="com.example.myapplication.C" android:label="fragment_c" tools:layout="@layout/fragment_c"> <action android:id="@+id/action_c_to_a" app:destination="@id/a" app:popUpTo="@+id/a" app:popUpToInclusive="true"/> </fragment>
Une fois la destination C atteinte, la pile "Retour" contient une instance de chaque destination (A, B, C). Pour revenir à la destination A, nous ajoutons également popUpTo
A. B et C seront donc supprimés de la pile pendant la navigation. Avec app:popUpToInclusive="true"
, nous supprimons également ce premier A de la pile et nous l'effaçons. Notez que si vous n'utilisez pas app:popUpToInclusive
, la pile "Retour" contiendra deux instances de la destination A.
popUpToSaveState et restoreSaveState
Lorsque vous utilisez app:popUpTo
pour naviguer vers une destination, Navigation 2.4.0-alpha01 et les versions ultérieures vous permettent d'enregistrer les états de toutes les destinations la pile "Retour". Pour activer cette option, incluez app:popUpToSaveState="true"
dans l'élément <action>
associé :
<action
android:id="@+id/action_c_to_a"
app:destination="@id/a"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"
app:popUpToSaveState="true"/>
Lorsque vous accédez à une destination, vous pouvez également inclure app:restoreSaveState="true"
pour restaurer automatiquement l'état qui lui est associé dans app:destination
.