Navigation 组件提供了一种导航到目的地的简单通用方式。此接口支持一系列上下文和界面框架。例如,您可以将 Navigation 组件与 Compose、View、fragment、activity 甚至自定义界面框架结合使用。
本指南介绍了如何使用 Navigation 组件在各种上下文中导航到目的地。
使用 NavController
您在目的地之间移动时所用的密钥类型是 NavController
。如需详细了解该类本身以及如何创建它的实例,请参阅创建导航控制器。本指南将详细介绍其使用方法。
导航
无论您使用哪种界面框架,都可以使用单个函数导航到目的地: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()
。不过,该函数有一系列过载,可供您在不同上下文中使用,以及与任何界面框架搭配使用。如需详细了解这些过载,请参阅参考文档。
深入阅读
如需了解详情,请参阅以下页面: