Zagnieżdżone wykresy

Zwykle najlepiej sprawdzają się przepływy logowania, kreatory i inne elementy podrzędne w aplikacji w postaci zagnieżdżonych wykresów nawigacyjnych. Przez zagnieżdżenie samodzielnej w ten sposób, główny przebieg interfejsu użytkownika aplikacji jest łatwiejszy rozumieć i nim zarządzać.

Poza tym wykresów zagnieżdżonych można używać wielokrotnie. Zapewniają też poziom hermetyzacja – miejsca docelowe poza zagnieżdżonym wykresem nie mają bezpośredniego dostępu do dowolnego z miejsc docelowych w zagnieżdżonym wykresie. Zamiast tego navigate() do zagnieżdżonego wykresu, gdzie logika wewnętrzna bez wpływu na pozostałą część wykresu.

Przykład

Wykres nawigacyjny najwyższego poziomu aplikacji powinien zaczynać się od początkowego miejsce docelowe, które widzi użytkownik przy uruchamianiu aplikacji, i powinno zawierać parametr miejsc docelowych, które widzą, poruszając się po Twojej aplikacji.

Rysunek 1. Wykres nawigacyjny najwyższego poziomu.

Na przykładzie wykresu nawigacji najwyższego poziomu z ilustracji 1 załóżmy, chciał, by użytkownik widział ekrany title_screen i register tylko przy pierwszym uruchomieniu aplikacji. Później dane użytkownika i podejmuje odpowiednie działania, do ekranu dopasowania.

Zalecamy ustawienie ekranu dopasowania jako miejsca docelowego na wykresie nawigacyjnym najwyższego poziomu, a następnie przenieś ekrany z tytułem i rejestru do zagnieżdżonego tak jak na ilustracji 1:

Rysunek 2. Wykres nawigacyjny najwyższego poziomu zawiera teraz wykres zagnieżdżony.

Gdy pojawi się ekran dopasowania, sprawdź, czy występuje na nim zarejestrowany użytkownik. Jeśli użytkownik nie jest zarejestrowany, przejdź do ekranu rejestracji.

Więcej informacji na temat scenariuszy warunkowej nawigacji znajdziesz w sekcji Informacje warunkowe nawigacji.

Compose

Aby utworzyć zagnieżdżony wykres nawigacyjny za pomocą funkcji Utwórz, użyj funkcji NavGraphBuilder.navigation(). Korzystasz z navigation() tak samo jak NavGraphBuilder.composable() i NavGraphBuilder.dialog() przy dodawaniu miejsc docelowych do wykresu.

Podstawowa różnica polega na tym, że funkcja navigation tworzy wykres zagnieżdżony, a nie nowe miejsce docelowe. Następnie dzwonisz pod numery composable() i dialog() w ciągu Funkcja lambda funkcji navigation() pozwala dodać miejsca docelowe do zagnieżdżonego wykresu.

Zastanów się, jak ten fragment kodu implementuje wykres z rysunku 2 za pomocą Utwórz:

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

Aby nawigować bezpośrednio do zagnieżdżonego miejsca docelowego, użyj typu trasy w taki sam sposób, jak do żadnego innego miejsca docelowego. Dzieje się tak, ponieważ trasy to koncepcja globalna używana do Określaj miejsca docelowe, do których mogą przejść każdy ekran:

navController.navigate(route = Match)

XML

Jeśli korzystasz z formatu XML, wykres zagnieżdżony możesz utworzyć w Edytorze nawigacji. W tym celu wykonaj następujące czynności:

  1. W edytorze nawigacji naciśnij i przytrzymaj klawisz Shift, a następnie kliknij miejsca docelowe, które chcesz uwzględnić na wykresie zagnieżdżonym.
  2. Kliknij prawym przyciskiem myszy, aby otworzyć menu kontekstowe, i wybierz Przenieś do wykresu zagnieżdżonego > Nowy wykres. Miejsca docelowe są przedstawione w zagnieżdżonym wykresie. Rysunek 2 pokazuje zagnieżdżony wykres w Edytorze nawigacji:

    Rys. 2. Wykres zagnieżdżony w edytorze nawigacji
  3. Kliknij wykres zagnieżdżony. W sekcji Panel Atrybuty:

    • Typ, który zawiera „Zagnieżdżony wykres”.
    • Identyfikator: zawiera przypisany przez system identyfikator zagnieżdżonego wykresu. Ten Identyfikator służy do odwoływania się do zagnieżdżonego wykresu w kodzie.
  4. Kliknij dwukrotnie wykres zagnieżdżony, aby wyświetlić jego miejsca docelowe.

  5. Kliknij kartę Tekst, aby przełączyć się na widok XML. Zagnieżdżony wykres nawigacyjny dodano do wykresu. Ten wykres nawigacyjny ma własną wartość navigation z własnym identyfikatorem i atrybutem startDestination, który wskazuje pierwsze miejsce docelowe na zagnieżdżonym wykresie:

    <?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. Przekaż w kodzie identyfikator zasobu działania, który łączy wykres główny na wykresie zagnieżdżonym:

Kotlin

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

Java

Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
  1. Na karcie Projekt wróć do wykresu głównego, klikając Strona główna.

Zapoznaj się z innymi wykresami nawigacyjnymi z uwzględnieniem

Innym sposobem na modułowe stworzenie struktury grafu jest uwzględnienie jednego wykresu w inne przy użyciu elementu <include> na nadrzędnym wykresie nawigacyjnym. Ten umożliwia zdefiniowanie uwzględnionego wykresu w osobnym module lub projekcie co pozwala zmaksymalizować ponowne wykorzystanie.

Ten fragment kodu ilustruje, jak można korzystać z elementu <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>

Dodatkowe materiały

Aby dowiedzieć się więcej o nawigacji, zapoznaj się z tymi dodatkowymi materiałami.

Próbki

Ćwiczenia z programowania

Filmy