Grafik bertingkat

Alur login, wizard, atau sub-alur lainnya dalam aplikasi biasanya direpresentasikan dengan baik sebagai grafik navigasi bertingkat. Dengan memberi tingkat alur subnavigasi mandiri dengan cara ini, alur utama UI aplikasi Anda akan lebih mudah dipahami dan dikelola.

Selain itu, grafik bertingkat dapat digunakan kembali. Class ini juga menyediakan tingkat enkapsulasi—tujuan di luar grafik bertingkat tidak memiliki akses langsung ke setiap tujuan dalam grafik bertingkat. Sebaliknya, grafik akan navigate() ke grafik bertingkat itu sendiri, di mana logika internal dapat berubah tanpa memengaruhi grafik lainnya.

Contoh

Grafik navigasi tingkat atas Anda harus dimulai dengan tujuan awal yang dilihat pengguna saat meluncurkan aplikasi dan harus menyertakan tujuan yang dilihat pengguna saat berpindah-pindah dalam aplikasi Anda.

Gambar 1. Grafik navigasi tingkat atas.

Dengan menggunakan grafik navigasi tingkat atas dari gambar 1 sebagai contoh, Anda ingin meminta pengguna untuk melihat title_screen dan layar register hanya saat aplikasi diluncurkan pertama kali. Setelah itu, informasi pengguna akan disimpan, dan pada peluncuran aplikasi berikutnya, sebaiknya Anda membawanya langsung ke layar match.

Sebagai praktik terbaik, tetapkan layar match sebagai tujuan awal grafik navigasi tingkat atas dan pindahkan layar judul dan daftar ke dalam grafik bertingkat, seperti yang ditunjukkan pada gambar 1:

Gambar 2. Grafik navigasi tingkat atas kini berisi grafik bertingkat.

Saat layar pencocokan (match) diluncurkan, periksa apakah ada pengguna terdaftar. Jika pengguna tidak terdaftar, arahkan pengguna ke layar pendaftaran.

Untuk informasi selengkapnya tentang skenario navigasi bersyarat, lihat Navigasi kondisional.

Compose

Untuk membuat grafik navigasi bertingkat menggunakan Compose, gunakan fungsi NavGraphBuilder.navigation(). Anda menggunakan navigation() seperti fungsi NavGraphBuilder.composable() dan NavGraphBuilder.dialog() saat menambahkan tujuan ke grafik.

Perbedaan utamanya adalah navigation membuat grafik bertingkat, bukan tujuan baru. Selanjutnya, Anda memanggil composable dan dialog dalam lambda navigation untuk menambahkan tujuan ke grafik bertingkat.

Pertimbangkan cara cuplikan berikut mengimplementasikan grafik pada gambar 2 menggunakan Compose:

NavHost(navController, startDestination = "title_screen") {
    composable("title_screen") {
        TitleScreen(
            onPlayClicked = { navController.navigate("register") },
            onLeaderboardsClicked = { /* Navigate to leaderboards */ }
        )
    }
    composable("register") {
        RegisterScreen(
            onSignUpComplete = { navController.navigate("gameInProgress") }
        )
    }
    navigation(startDestination = "match", route = "gameInProgress") {
        composable("match") {
            MatchScreen(
                onStartGame = { navController.navigate("in_game") }
            )
        }
        composable("in_game") {
            InGameScreen(
                onGameWin = { navController.navigate("results_winner") },
                onGameLose = { navController.navigate("game_over") }
            )
        }
        composable("results_winner") {
            ResultsWinnerScreen(
                onNextMatchClicked = {
                    navController.navigate("match") {
                        popUpTo("match") { inclusive = true }
                    }
                },
                onLeaderboardsClicked = { /* Navigate to leaderboards */ }
            )
        }
        composable("game_over") {
            GameOverScreen(
                onTryAgainClicked = {
                    navController.navigate("match") {
                        popUpTo("match") { inclusive = true }
                    }
                }
            )
        }
    }
}

Untuk menavigasi langsung ke tujuan bertingkat, gunakan route seperti yang Anda lakukan ke tujuan lainnya. Hal ini karena rute adalah konsep global yang dapat dibuka oleh layar apa pun:

navController.navigate("match")

Fungsi ekstensi

Anda dapat menambahkan tujuan ke grafik menggunakan fungsi ekstensi di NavGraphBuilder. Anda dapat menggunakan fungsi ekstensi ini bersama metode ekstensi navigation, composable, dan dialog bawaan.

Misalnya, Anda dapat menggunakan fungsi ekstensi untuk menambahkan grafik bertingkat yang ditunjukkan di bagian sebelumnya:

fun NavGraphBuilder.addNestedGraph(navController: NavController) {
    navigation(startDestination = "match", route = "gameInProgress") {
        composable("match") {
            MatchScreen(
                onStartGame = { navController.navigate("in_game") }
            )
        }
        composable("in_game") {
            InGameScreen(
                onGameWin = { navController.navigate("results_winner") },
                onGameLose = { navController.navigate("game_over") }
            )
        }
        composable("results_winner") {
            ResultsWinnerScreen(
                onNextMatchClicked = { navController.navigate("match") },
                onLeaderboardsClicked = { /* Navigate to leaderboards */ }
            )
        }
        composable("game_over") {
            GameOverScreen(
                onTryAgainClicked = { navController.navigate("match") }
            )
        }
    }
}

Anda kemudian dapat memanggil fungsi ini di lambda yang diteruskan ke NavHost, bukan memanggil navigasi inline. Contoh berikut menunjukkan hal tersebut:

@Composable
fun MyApp() {
    val navController = rememberNavController()
    NavHost(navController, startDestination = "title_screen") {
        composable("title_screen") {
            TitleScreen(
                onPlayClicked = { navController.navigate("register") },
                onLeaderboardsClicked = { /* Navigate to leaderboards */ }
            )
        }
        composable("register") {
            RegisterScreen(
                onSignUpComplete = { navController.navigate("gameInProgress") }
            )
        }

        // Add the nested graph using the extension function
        addNestedGraph(navController)
    }
}

XML

Saat menggunakan XML, Anda dapat menggunakan Navigation Editor untuk membuat grafik bertingkat. Untuk melakukannya, ikuti langkah-langkah berikut:

  1. Di Navigation Editor, tekan dan tahan tombol Shift, lalu klik tujuan yang ingin Anda sertakan dalam grafik bertingkat.
  2. Klik kanan untuk membuka menu konteks, lalu pilih Move to Nested Graph > New Graph. Tujuan dimasukkan dalam grafik bertingkat. Gambar 2 menunjukkan grafik bertingkat dalam Navigation Editor:

    Gambar 2. Grafik bertingkat di Editor Navigasi
  3. Klik grafik bertingkat. Atribut berikut muncul dalam panel Attributes:

    • Type, yang berisi "Grafik Bertingkat"
    • ID, yang berisi ID yang ditetapkan sistem untuk grafik bertingkat. ID ini digunakan untuk mereferensikan grafik bertingkat dari kode Anda.
  4. Klik dua kali pada grafik bertingkat untuk menampilkan tujuannya.

  5. Klik tab Text untuk beralih ke tampilan XML. Grafik navigasi bertingkat telah ditambahkan ke grafik. Grafik navigasi ini memiliki elemen navigation tersendiri bersama ID-nya sendiri dan atribut startDestination yang mengarah ke tujuan pertama dalam grafik bertingkat:

    <?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. Dalam kode Anda, teruskan ID resource tindakan yang menghubungkan grafik root ke grafik bertingkat:

    kotlin

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

    java

    Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
    
  7. Kembali ke tab Design, kembali ke grafik root dengan mengklik Root.

Merujuk grafik navigasi lain dengan include

Cara lain untuk memodularisasi struktur grafik Anda adalah menyertakan satu grafik dalam grafik lain menggunakan elemen <include> di grafik navigasi induk. Hal ini memungkinkan grafik yang disertakan untuk ditentukan dalam modul terpisah atau project sama sekali, yang memaksimalkan penggunaan kembali.

Cuplikan berikut menunjukkan cara menggunakan <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>

Referensi lainnya

Untuk mempelajari navigasi lebih lanjut, lihat referensi tambahan berikut.

Contoh

Codelab

Video