Graphiques imbriqués

Les flux de connexion, les assistants ou d'autres sous-flux dans votre application sont généralement représentés par des graphiques de navigation imbriqués. En imbriquant ainsi les flux de sous-navigation autonomes, le flux principal de l'UI de votre application est plus facile à comprendre et à gérer.

De plus, les graphiques imbriqués sont réutilisables. Ils fournissent également un niveau d'encapsulation. En effet, les destinations situées en dehors du graphique imbriqué n'ont pas un accès direct aux destinations du graphique imbriqué. À la place, elles doivent naviguer (navigate()) jusqu'au graphique imbriqué lui-même, où la logique interne peut changer sans affecter le reste du graphique.

Exemple

Le graphique de navigation de premier niveau de votre application doit commencer par la destination initiale que l'utilisateur voit lorsqu'il lance l'application et doit inclure les destinations qu'il voit lorsqu'il se déplace dans votre application.

Figure 1. Un graphique de navigation de premier niveau

En utilisant le graphique de navigation de premier niveau de la figure 1 comme exemple, supposons que vous souhaitiez que l'utilisateur ne voie les écrans title_screen et register que lors du premier lancement de l'application. Par la suite, les informations utilisateur sont stockées. Lors des lancements suivants de l'application, vous devez les rediriger directement vers l'écran match (correspondance).

Il est recommandé de définir l'écran match (correspondance) comme destination de départ du graphique de navigation de premier niveau, puis de déplacer les écrans de titre et d'inscription dans un graphique imbriqué, comme illustré dans la figure 1:

Figure 2 : Le graphique de navigation de premier niveau contient désormais un graphique imbriqué.

Lorsque l'écran de correspondance se lance, vérifiez si un utilisateur est enregistré. Si l'utilisateur n'est pas enregistré, accédez à l'écran d'inscription.

Pour en savoir plus sur les scénarios de navigation conditionnelle, consultez la page Navigation conditionnelle.

Compose

Pour créer un graphique de navigation imbriqué à l'aide de Compose, utilisez la fonction NavGraphBuilder.navigation(). Vous utilisez navigation() tout comme les fonctions NavGraphBuilder.composable() et NavGraphBuilder.dialog() lorsque vous ajoutez des destinations à un graphique.

La principale différence est que navigation crée un graphique imbriqué plutôt qu'une nouvelle destination. Appelez ensuite composable() et dialog() dans le lambda de navigation() pour ajouter des destinations au graphique imbriqué.

Examinons comment l'extrait suivant implémente le graphique de la figure 2 à l'aide de Compose :

// Routes
@Serializable object Title
@Serializable object Register

// Route for nested graph
@Serializable object Game

// Routes inside nested graph
@Serializable object Match
@Serializable object InGame
@Serializable object ResultsWinner
@Serializable object GameOver

NavHost(navController, startDestination = Title) {
   composable<Title> {
       TitleScreen(
           onPlayClicked = { navController.navigate(route = Register) },
           onLeaderboardsClicked = { /* Navigate to leaderboards */ }
       )
   }
   composable<Register> {
       RegisterScreen(
           onSignUpComplete = { navController.navigate(route = Game) }
       )
   }
   navigation<Game>(startDestination = Match) {
       composable<Match> {
           MatchScreen(
               onStartGame = { navController.navigate(route = InGame) }
           )
       }
       composable<InGame> {
           InGameScreen(
               onGameWin = { navController.navigate(route = ResultsWinner) },
               onGameLose = { navController.navigate(route = GameOver) }
           )
       }
       composable<ResultsWinner> {
           ResultsWinnerScreen(
               onNextMatchClicked = {
                   navController.navigate(route = Match) {
                       popUpTo(route = Match) { inclusive = true }
                   }
               },
               onLeaderboardsClicked = { /* Navigate to leaderboards */ }
           )
       }
       composable<GameOver> {
           GameOverScreen(
               onTryAgainClicked = {
                   navController.navigate(route = Match) {
                       popUpTo(route = Match) { inclusive = true }
                   }
               }
           )
       }
   }
}

Pour accéder directement à une destination imbriquée, utilisez un type de route comme vous le feriez pour n'importe quelle autre destination. En effet, les routes sont un concept global utilisé pour identifier les destinations vers lesquelles n'importe quel écran peut naviguer:

navController.navigate(route = Match)

XML

Lorsque vous utilisez le format XML, vous pouvez utiliser l'éditeur de navigation pour créer votre graphique imbriqué. Pour cela, procédez comme suit :

  1. Dans l'éditeur de navigation, appuyez de manière prolongée sur la touche Maj, puis cliquez sur les destinations que vous souhaitez inclure dans le graphique imbriqué.
  2. Effectuez un clic droit pour ouvrir le menu contextuel, puis sélectionnez Move to Nested Graph > New Graph (Déplacer vers un graphique imbriqué > Nouveau graphique). Les destinations sont incluses dans un graphique imbriqué. La figure 2 montre un graphique imbriqué dans l'éditeur de navigation :

    Figure 2. Graphique imbriqué dans l'éditeur de navigation
  3. Cliquez sur le graphique imbriqué. Les attributs suivants apparaissent dans le panneau Attributes (Attributs) :

    • Type, qui contient "Nested Graph" (Graphique imbriqué)
    • ID, qui contient un ID attribué par le système pour le graphique imbriqué Cet ID permet de référencer le graphique imbriqué de votre code.
  4. Double-cliquez sur le graphique imbriqué pour afficher ses destinations.

  5. Cliquez sur l'onglet Text (Texte) pour passer à la vue XML. Un graphique de navigation imbriqué y a été ajouté. Ce graphique de navigation possède ses propres éléments navigation, ainsi que son propre ID et un attribut startDestination qui pointe vers la première destination du graphique imbriqué :

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:app="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       xmlns:android="http://schemas.android.com/apk/res/android"
       app:startDestination="@id/mainFragment">
       <fragment
           android:id="@+id/mainFragment"
           android:name="com.example.cashdog.cashdog.MainFragment"
           android:label="fragment_main"
           tools:layout="@layout/fragment_main" >
           <action
               android:id="@+id/action_mainFragment_to_sendMoneyGraph"
               app:destination="@id/sendMoneyGraph" />
           <action
               android:id="@+id/action_mainFragment_to_viewBalanceFragment"
               app:destination="@id/viewBalanceFragment" />
       </fragment>
       <fragment
           android:id="@+id/viewBalanceFragment"
           android:name="com.example.cashdog.cashdog.ViewBalanceFragment"
           android:label="fragment_view_balance"
           tools:layout="@layout/fragment_view_balance" />
       <navigation android:id="@+id/sendMoneyGraph" app:startDestination="@id/chooseRecipient">
           <fragment
               android:id="@+id/chooseRecipient"
               android:name="com.example.cashdog.cashdog.ChooseRecipient"
               android:label="fragment_choose_recipient"
               tools:layout="@layout/fragment_choose_recipient">
               <action
                   android:id="@+id/action_chooseRecipient_to_chooseAmountFragment"
                   app:destination="@id/chooseAmountFragment" />
           </fragment>
           <fragment
               android:id="@+id/chooseAmountFragment"
               android:name="com.example.cashdog.cashdog.ChooseAmountFragment"
               android:label="fragment_choose_amount"
               tools:layout="@layout/fragment_choose_amount" />
       </navigation>
    </navigation>
    
  6. Dans votre code, transmettez l'ID de ressource de l'action qui connecte le graphique racine au graphique imbriqué :

    kotlin

    view.findNavController().navigate(R.id.action_mainFragment_to_sendMoneyGraph)
    

    java

    Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
    
  7. Revenez dans l'onglet Design (Conception), puis accédez de nouveau au graphique racine en cliquant sur Root (Racine).

Référencer d'autres graphiques de navigation avec un élément "include"

Vous pouvez également modulariser la structure de votre graphique en incluant un graphique dans un autre à l'aide d'un élément <include> dans le graphique de navigation parent. Le graphique inclus peut ainsi être défini dans un module ou un projet distinct, ce qui optimise sa réutilisation.

L'extrait suivant montre comment utiliser <include> :

<!-- (root) nav_graph.xml -->
<?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/fragment">

    <strong><include app:graph="@navigation/included_graph" /></strong>

    <fragment
        android:id="@+id/fragment"
        android:name="com.example.myapplication.BlankFragment"
        android:label="Fragment in Root Graph"
        tools:layout="@layout/fragment_blank">
        <strong><action
            android:id="@+id/action_fragment_to_second_graph"
            app:destination="@id/second_graph" /></strong>
    </fragment>

    ...
</navigation>
<!-- included_graph.xml -->
<?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"
    <strong>android:id="@+id/second_graph"</strong>
    app:startDestination="@id/includedStart">

    <fragment
        android:id="@+id/includedStart"
        android:name="com.example.myapplication.IncludedStart"
        android:label="fragment_included_start"
        tools:layout="@layout/fragment_included_start" />
</navigation>

Ressources supplémentaires

Pour en savoir plus sur la navigation, consultez les ressources supplémentaires suivantes.

Exemples

Ateliers de programmation

Vidéos