Navigation 元件使用「導覽圖」管理應用程式的導覽。導覽圖是一種資料結構,其中包含應用程式內的各個目的地,以及目的地之間的連結。
目的地類型
目的地分為三種一般類型:代管、對話方塊和活動。下表概述這三種目的地類型及其用途。
| 類型 | 說明 | 用途 | 
|---|---|---|
| 代管 | 會填滿整個導覽主機。也就是說,代管目的地與導覽主機大小相同,因此無法顯示先前的目的地。 | 主要畫面和詳細資料畫面。 | 
| 對話方塊 | 會顯示重疊的 UI 元件。此 UI 與導覽主機的位置或大小無關,先前的目的地可顯示在此目的地底下。 | 快訊、選取項目、表單。 | 
| 活動 | 代表應用程式內的獨特畫面或功能。 | 做為導覽圖的結束點,啟動與該 Navigation 元件分開管理的新 Android 活動。 在 Modern Android Development 中,應用程式是由單一活動組成。因此,活動目的地最適合用於與第三方活動互動,或做為遷移程序的一部分。 | 
本文件提供代管目的地的範例,這是最常見、也是基本的目的地。如需其他目的地的資訊,請參閱下列指南:
架構
雖然所有情況都適用相同的一般工作流程,但還是要根據所用 UI 架構,決定建立導覽主機和導覽圖的確切方式。
- Compose:使用 NavHost可組合函式。使用 Kotlin DSL 為這個可組合函式新增NavGraph。您可以透過下列兩種方式建立圖表:- 做為 NavHost 的一部分:直接在新增 NavHost的過程中建構導覽圖。
- 透過程式輔助方式:使用 NavController.createGraph()方法建立NavGraph並直接傳遞至NavHost。
 
- 做為 NavHost 的一部分:直接在新增 
- Fragment:搭配檢視區塊 UI 架構使用片段時,請使用 NavHostFragment做為主機。您可以透過下列幾種方式建立導覽圖:- 透過程式輔助方式:使用 Kotlin DSL 建立 NavGraph,並直接套用至NavHostFragment。- 無論是採用片段或 Compose 建立導覽圖,搭配 Kotlin DSL 使用的 createGraph()函式皆相同。
 
- 無論是採用片段或 Compose 建立導覽圖,搭配 Kotlin DSL 使用的 
- XML:直接以 XML 編寫導覽主機和導覽圖。
- Android Studio 編輯器:使用 Android Studio 中的 GUI 編輯器,以 XML 資源檔案的形式建立及調整導覽圖。
 
- 透過程式輔助方式:使用 Kotlin DSL 建立 
Compose
在 Compose 中,使用可序列化物件或類別來定義路徑。路線會說明如何前往目的地,並包含目的地所需的所有資訊。
使用 @Serializable 註解,自動為路徑類型建立必要的序列化和反序列化方法。此註解由 Kotlin 序列化外掛程式提供。請按照這些操作說明新增這個外掛程式。
定義路徑後,請使用 NavHost 可組合項建立導覽圖。請參考以下範例:
@Serializable
object Profile
@Serializable
object FriendsList
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Profile) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
    // Add more destinations similarly.
}
- 可序列化的物件代表兩個路線:Profile和FriendsList。
- 對 NavHost可組合函式的呼叫會傳遞NavController和起始目的地的路線。
- 傳遞至 NavHost的 lambda 最終會呼叫NavController.createGraph()並傳回NavGraph。
- 每條路線都會做為類型引數提供給 NavGraphBuilder.composable<T>(),後者會將目的地新增至產生的NavGraph。
- 傳送至 composable的 lambda 是NavHost針對該目的地顯示的內容。
瞭解 lambda
如要進一步瞭解會建立 NavGraph 的 lambda,建議您建立與前述程式碼片段相同的圖表,使用 NavController.createGraph() 單獨建立 NavGraph,並直接傳遞至 NavHost:
val navGraph by remember(navController) {
  navController.createGraph(startDestination = Profile)) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)
傳遞引數
如果您需要將資料傳遞至目的地,請使用含有參數的類別定義路徑。例如,Profile 路徑是含有 name 參數的資料類別。
@Serializable
data class Profile(val name: String)
每當您需要將引數傳遞至該目的地時,請建立路徑類別的例項,並將引數傳遞至類別建構函式。
針對選用引數,請建立具有預設值的可為空值欄位。
@Serializable
data class Profile(val nickname: String? = null)
取得路線例項
您可以使用 NavBackStackEntry.toRoute() 或 SavedStateHandle.toRoute() 取得路由例項。使用 composable() 建立目的地時,NavBackStackEntry 可做為參數使用。
@Serializable
data class Profile(val name: String)
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Profile(name="John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(name = profile.name) }
}
請注意這個程式碼片段中的以下事項:
- Profile路線會在導航圖表中指定起始目的地,並將- "John Smith"做為- name的引數。
- 目的地本身就是 composable<Profile>{}區塊。
- ProfileScreen可組合函式會將- profile.name的值設為其- name引數。
- 因此,值 "John Smith"會傳遞至ProfileScreen。
最簡單的範例
以下是 NavController 和 NavHost 如何共同運作的完整範例:
@Serializable
data class Profile(val name: String)
@Serializable
object FriendsList
// Define the ProfileScreen composable.
@Composable
fun ProfileScreen(
    profile: Profile
    onNavigateToFriendsList: () -> Unit,
  ) {
  Text("Profile for ${profile.name}")
  Button(onClick = { onNavigateToFriendsList() }) {
    Text("Go to Friends List")
  }
}
// Define the FriendsListScreen composable.
@Composable
fun FriendsListScreen(onNavigateToProfile: () -> Unit) {
  Text("Friends List")
  Button(onClick = { onNavigateToProfile() }) {
    Text("Go to Profile")
  }
}
// Define the MyApp composable, including the `NavController` and `NavHost`.
@Composable
fun MyApp() {
  val navController = rememberNavController()
  NavHost(navController, startDestination = Profile(name = "John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(
            profile = profile,
            onNavigateToFriendsList = {
                navController.navigate(route = FriendsList)
            }
        )
    }
    composable<FriendsList> {
      FriendsListScreen(
        onNavigateToProfile = {
          navController.navigate(
            route = Profile(name = "Aisha Devi")
          )
        }
      )
    }
  }
}
如程式碼片段所示,您應向 NavHost 公開事件,而不是將 NavController 傳遞至可組合函式。也就是說,可組合函式應提供 () -> Unit 類型的參數,讓 NavHost 傳遞呼叫 NavController.navigate() 的 lambda。
片段
如先前章節所述,使用片段時,您可以選擇使用 Kotlin DSL、XML 或 Android Studio 編輯器,透過程式輔助方式建立導覽圖。
以下各節將詳細說明這些不同做法。
透過程式輔助方式
Kotlin DSL 支援透過程式輔助方式,使用片段建立導覽圖。在許多方面,這種做法比使用 XML 資源檔案更簡潔,採用更現代化的技術。
請參考以下範例,當中會實作具有兩個畫面的導覽圖。
首先需要建立 NavHostFragment,其中「不得」包含 app:navGraph 元素:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
接下來,將 NavHostFragment 的 id 傳遞給 NavController.findNavController,這會將 NavController 與 NavHostFragment 建立關聯。
隨後,呼叫 NavController.createGraph() 會將圖表連結至 NavController,因此也會連結至 NavHostFragment:
@Serializable
data class Profile(val name: String)
@Serializable
object FriendsList
// Retrieve the NavController.
val navController = findNavController(R.id.nav_host_fragment)
// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = Profile(name = "John Smith")
) {
    // Associate each destination with one of the route constants.
    fragment<ProfileFragment, Profile> {
        label = "Profile"
    }
    fragment<FriendsListFragment, FriendsList>() {
        label = "Friends List"
    }
    // Add other fragment destinations similarly.
}
透過這種方式使用 DSL 與先前 Compose 一節所述的工作流程非常相似。例如,在這兩個流程中,NavController.createGraph() 函式都會產生 NavGraph。同樣地,NavGraphBuilder.composable() 會在圖表中加入可組合函式目的地,此處的 NavGraphBuilder.fragment() 則會加入片段目的地。
如要進一步瞭解如何使用 Kotlin DSL,請參閱「使用 NavGraphBuilder DSL 建構圖表」一文。
XML
您可以直接自行編寫 XML。以下範例等同於上一節的兩個畫面範例,會產生相同結果。
首先建立 NavHostFragment,做為包含實際導覽圖的導覽主機。
最簡單的 NavHostFragment 實作方式:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph" />
</FrameLayout>
NavHostFragment 包含 app:navGraph 屬性。請使用這項屬性將導覽圖連結至導覽主機。以下範例說明如何實作圖表:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/profile">
    <fragment
        android:id="@+id/profile"
        android:name="com.example.ProfileFragment"
        android:label="Profile">
        <!-- Action to navigate from Profile to Friends List. -->
        <action
            android:id="@+id/action_profile_to_friendslist"
            app:destination="@id/friendslist" />
    </fragment>
    <fragment
        android:id="@+id/friendslist"
        android:name="com.example.FriendsListFragment"
        android:label="Friends List" />
    <!-- Add other fragment destinations similarly. -->
</navigation>
您可以使用動作定義不同目的地之間的連結。在本範例中,profile 片段包含前往 friendslist 的動作。詳情請參閱「使用導覽動作和片段」。
編輯者
您可以使用 Android Studio 中的 Navigation 編輯器管理應用程式的導覽圖。基本上,這個編輯器就是可用來建立及編輯 NavigationFragment XML 的 GUI,如上一節所示。
詳情請參閱「Navigation 編輯器」。
巢狀結構圖
您也可以使用巢狀結構圖,也就是使用圖表做為導覽目的地。詳情請參閱「巢狀結構圖」。
其他資訊
如要進一步瞭解核心導覽概念,請參閱下列指南:
- 總覽:請務必詳閱 Navigation 元件的一般總覽。
- 活動目的地:提供多個範例,說明如何實作會將使用者導向至活動的目的地。
- 對話方塊目的地:提供多個範例,說明如何建立會將使用者導向至對話方塊的目的地。
- 前往目的地:內容詳盡的指南,說明如何從某個目的地導覽至另一個目的地。
- 巢狀結構圖:提供深入指南,說明如何運用巢狀結構在一個導覽圖內置入另一個導覽圖。
