导航组件提供了一种简单而通用的导航到目标的方法。此界面支持一系列上下文和 UI 框架。例如,您可以将导航组件与 Compose、视图、片段、活动甚至自定义 UI 框架一起使用。
本指南介绍了如何使用导航组件在各种上下文中导航到目标。
使用 NavController
在目标之间移动时使用的关键类型是 NavController
。有关该类本身以及如何创建其实例的更多信息,请参阅 创建导航控制器。本指南详细介绍了如何使用它。
导航
无论您使用哪种 UI 框架,都可以使用单个函数导航到目标:NavController.navigate()
。
有许多可用于 navigate()
的重载。您应该选择的重载对应于您的确切上下文。例如,导航到可组合项时应使用一个重载,导航到视图时应使用另一个重载。
以下部分概述了一些您可以使用的关键 navigate()
重载。
导航到可组合项
要导航到可组合项,您应该使用 NavController.navigate<T>
。在此重载中,navigate()
采用一个 route
参数,您为其传递一个类型。它用作目标的关键。
@Serializable
object FriendsList
navController.navigate(route = FriendsList)
要导航到导航图中的可组合项,首先定义您的 NavGraph
,以便 每个目标对应于一个类型。对于可组合项,您可以使用 composable()
函数来执行此操作。
公开可组合项中的事件
当可组合函数需要导航到新屏幕时,您不应将对 NavController
的引用传递给它,以便它可以直接调用 navigate()
。根据 单向数据流 (UDF) 原则,可组合项应改为公开一个由 NavController
处理的事件。
更直接地说,您的可组合项应该具有类型为 () -> Unit
的参数。当您使用 composable()
函数将目标添加到 NavHost
时,请将对 NavController.navigate()
的调用传递给您的可组合项。
有关示例,请参阅以下小节。
示例
为了演示前面各节,请在以下代码段中观察以下几点
- 图中的每个目标都是使用路由创建的,路由是描述该目标所需数据的可序列化对象或类。
MyAppNavHost
可组合项持有NavController
实例。- 因此,对
navigate()
的调用应该在那里发生,而不是在较低的可组合项(如ProfileScreen
)中发生。 ProfileScreen
包含一个按钮,点击该按钮可将用户导航到FriendsList
。但是,它本身不调用navigate()
。- 相反,该按钮调用一个作为参数
onNavigateToFriends
公开的函数。 - 当
MyAppNavHost
将ProfileScreen
添加到导航图时,它会为onNavigateToFriends
传递一个调用navigate(route = FriendsList
) 的 lambda 表达式。 - 这确保了当用户按下
ProfileScreen
上的按钮时,可以正确地导航到FriendsListScreen
。
@Serializable
object Profile
@Serializable
object FriendsList
@Composable
fun MyAppNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = Profile
) {
composable<Profile> {
ProfileScreen(
onNavigateToFriends = { navController.navigate(route = FriendsList) },
/*...*/
)
}
composable<FriendsList> { FriendsListScreen(/*...*/) }
}
}
@Composable
fun ProfileScreen(
onNavigateToFriends: () -> Unit,
/*...*/
) {
/*...*/
Button(onClick = onNavigateToFriends) {
Text(text = "See friends list")
}
}
使用整数 ID 进行导航
要使用整数 ID 导航到目标位置,请调用 navigate(int)
重载。它接受操作或目标位置的资源 ID。以下代码片段演示了如何使用此重载导航到 ViewTransactionsFragment
Kotlin
viewTransactionsButton.setOnClickListener { view ->
view.findNavController().navigate(R.id.viewTransactionsAction)
}
Java
viewTransactionsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Navigation.findNavController(view).navigate(R.id.viewTransactionsAction);
}
});
在使用 ID 进行导航时,应尽可能使用 操作。操作在导航图中提供其他信息,直观地显示目标位置如何相互连接。
使用 NavDeepLinkRequest 进行导航
要导航到 隐式深度链接目标位置,请使用 navigate(NavDeepLinkRequest)
重载。以下代码段提供了此方法的实现
Kotlin
val request = NavDeepLinkRequest.Builder
.fromUri("android-app://androidx.navigation.app/profile".toUri())
.build()
findNavController().navigate(request)
Java
NavDeepLinkRequest request = NavDeepLinkRequest.Builder
.fromUri(Uri.parse("android-app://androidx.navigation.app/profile"))
.build()
NavHostFragment.findNavController(this).navigate(request)
与使用操作或目标位置 ID 进行导航不同,您可以导航到图中的任何深度链接,无论目标位置是否可见。您可以导航到当前图上的目标位置或完全不同的图上的目标位置。
操作和 MIME 类型
除了 Uri
之外,NavDeepLinkRequest
还支持带有操作和 MIME 类型的深度链接。要将操作添加到请求中,请使用 fromAction()
或 setAction()
。要将 MIME 类型添加到请求中,请使用 fromMimeType()
或 setMimeType()
。
要使 NavDeepLinkRequest
正确匹配隐式深度链接目标位置,URI、操作和 MIME 类型必须全部与目标位置中的 NavDeepLink
匹配。URI 必须与模式匹配,操作必须完全匹配,MIME 类型必须相关。例如,image/jpg
与 image/\*
匹配
更多上下文
本文档介绍了如何在最常见的用例中使用 NavController.navigate()
。但是,该函数具有一系列重载,您可以在不同上下文中以及与任何 UI 框架一起使用这些重载。有关这些重载的更多详细信息,请参阅参考文档。
进一步阅读
有关更多信息,请参阅以下页面