导航组件提供了一种直接且通用的方式来导航到目标。此接口支持多种上下文和 UI 框架。例如,您可以将导航组件与 Compose、视图、Fragment、Activity 甚至自定义 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 框架配合使用。有关这些重载的更多详细信息,请参阅参考文档。
延伸阅读
有关更多信息,请参阅以下页面