导航组件提供了一种简单而通用的导航到目标的方法。此界面支持一系列上下文和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 框架一起使用。有关这些重载方法的更多详细信息,请参阅参考文档。
进一步阅读
更多信息,请参阅以下页面