Navigation 组件使用导航图管理应用导航。导航图是一种数据结构,包含应用内的每个目的地以及这些目的地之间的连接。
目的地类型
有三种常规类型的目的地:托管、对话框和 activity。下表概述了这三种目的地类型及其用途。
类型 |
说明 |
用例 |
|---|---|---|
托管 |
填充整个导航宿主。也就是说,托管目的地的大小与导航宿主的大小相同,之前的目的地不会显示。 |
主界面和详情界面。 |
对话框 |
显示叠加界面组件。此界面与导航宿主的位置或大小无关。之前的目的地会显示在该目的地下方。 |
提醒、选择、表单。 |
activity |
表示应用中的独特界面或功能。 |
充当导航图的退出点,启动与 Navigation 组件分开管理的新 Android activity。 在 Modern Android Development 中,应用由 1 个 activity 组成。因此,当与第三方 activity 互动或作为迁移过程的一部分时,最适合使用 activity 目的地。 |
本文档包含托管目的地的示例,这些目的地是最常用和最基本的目的地。如需了解其他目的地,请参阅以下指南:
框架
虽然相同的常规工作流适用于所有情况,但导航宿主和导航图的创建方式取决于您使用的界面框架。
- Compose:使用
NavHost可组合项。使用 Kotlin DSL 为其添加NavGraph。您可以通过以下两种方式创建图表:- 作为 NavHost 的一部分:在添加
NavHost的过程中直接构建导航图。 - 以编程方式:使用
NavController.createGraph()方法创建NavGraph并将其直接传递给NavHost。
- 作为 NavHost 的一部分:在添加
- fragment:将 fragment 与视图界面框架搭配使用时,请使用
NavHostFragment作为宿主。您可以通过多种方式创建导航图:- 以编程方式:使用 Kotlin DSL 创建
NavGraph并将其直接应用于NavHostFragment。- 与 Kotlin DSL 搭配用于 fragment 和 Compose 的
createGraph()函数是相同的。
- 与 Kotlin DSL 搭配用于 fragment 和 Compose 的
- 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)
每当您需要将参数传递给该目的地时,都需要创建路线类的实例,并将参数传递给类构造函数。
对于可选参数,请创建具有默认值的可为 null 的字段。
@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可组合项会为自己的name实参采用profile.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 =