Grafici nidificati

I flussi di accesso, le procedure guidate o altri flussi secondari all'interno dell'app sono in genere i migliori rappresentati come grafici di navigazione nidificati. Nidificando i dati indipendenti di navigazione secondaria in questo modo, il flusso principale dell'UI dell'app è più facile comprendere e gestire.

Inoltre, i grafici nidificati sono riutilizzabili. Inoltre, offrono un livello di incapsulamento: le destinazioni al di fuori del grafico nidificato non hanno accesso diretto a una qualsiasi delle destinazioni all'interno del grafico nidificato. Dovrebbero invece navigate() al grafico nidificato stesso, dove la logica interna può senza alterare il resto del grafico.

Esempio

Il grafico di navigazione di primo livello dell'app deve iniziare con la destinazione che l'utente vede all'avvio dell'app e deve includere le destinazioni che vedono mentre si spostano nell'app.

Figura 1. Un grafico di navigazione di primo livello.

Utilizzando come esempio il grafico di navigazione di primo livello della Figura 1, supponiamo che voleva richiedere all'utente di visualizzare le schermate title_screen e register solo quando l'app viene avviata per la prima volta. In seguito, i dati dell'utente è archiviato e, nei successivi lanci dell'app, è bene indirizzarli direttamente alla schermata delle corrispondenze.

Come best practice, imposta la schermata Corrispondenza come destinazione di partenza della grafico di navigazione di primo livello e spostare le schermate del titolo e di registrazione in un come mostrato nella figura 1:

Figura 2. Il grafico di navigazione di primo livello ora contiene un grafico nidificato.

Quando si avvia la schermata delle corrispondenze, verifica se esiste un utente registrato. Se l'utente non è registrato, spostati nella schermata di registrazione.

Per saperne di più sugli scenari della navigazione condizionale, consulta la sezione Informazioni sull'uso .

Compose

Per creare un grafico di navigazione nidificato utilizzando Compose, utilizza il NavGraphBuilder.navigation(). Utilizzi navigation() proprio come NavGraphBuilder.composable() e NavGraphBuilder.dialog() durante l'aggiunta di destinazioni a un grafico.

La differenza principale è che navigation crea un grafico nidificato anziché nuova destinazione. Poi chiama composable() e dialog() entro il comando lambda di navigation() per aggiungere destinazioni al grafico nidificato.

Considera come il seguente snippet implementa il grafico nella Figura 2 utilizzando Scrivi:

// 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 }
                   }
               }
           )
       }
   }
}

Per navigare direttamente verso una destinazione nidificata, utilizza un tipo di percorso come faresti per qualsiasi altra destinazione. Questo perché le route sono un concetto globale utilizzato identificare le destinazioni raggiungibili da qualsiasi schermata:

navController.navigate(route = Match)
.

XML

Se utilizzi XML, puoi usare l'editor di navigazione per creare il grafico nidificato. Per farlo, segui questi passaggi:

  1. Nell'editor di navigazione, tieni premuto il tasto Maiusc e fai clic sul le destinazioni da includere nel grafico nidificato.
  2. Fai clic con il tasto destro del mouse per aprire il menu contestuale e seleziona Sposta nel grafico nidificato > Nuovo grafico. Le destinazioni sono racchiuse in un grafico nidificato. Figura 2 mostra un grafico nidificato nell'Editor di navigazione:

    Figura 2. Grafico nidificato nell'editor di navigazione
  3. Fai clic sul grafico nidificato. Nella sezione Riquadro Attributi:

    • Tipo, che contiene "Grafico nidificato"
    • ID, che contiene un ID assegnato dal sistema per il grafico nidificato. Questo L'ID viene utilizzato per fare riferimento al grafico nidificato dal codice.
  4. Fai doppio clic sul grafico nidificato per visualizzarne le destinazioni.

  5. Fai clic sulla scheda Testo per passare alla visualizzazione XML. Un grafico di navigazione nidificato sono state aggiunte al grafico. Questo grafico di navigazione ha un proprio navigation elementi insieme al proprio ID e a un attributo startDestination che punta alla prima destinazione nel grafico nidificato:

    <?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. Nel codice, passa l'ID risorsa dell'azione che collega il grafico principale al grafico nidificato:

Kotlin

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

Java

Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
  1. Tornando alla scheda Design, torna al grafico principale facendo clic su Radice.

Fai riferimento ad altri grafici di navigazione con Includi

Un altro modo per modularizzare la struttura del grafico è includere un grafico all'interno un'altra utilizzando un elemento <include> nel grafico di navigazione principale. Questo consente di definire il grafo incluso in un modulo o progetto separato nel complesso, il che massimizza la riusabilità.

Il seguente snippet mostra come utilizzare <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>

Risorse aggiuntive

Per saperne di più sulla navigazione, consulta le seguenti risorse aggiuntive.

Campioni

Codelab

Video