导航到目标

导航组件提供了一种简单而通用的导航到目标的方法。此界面支持一系列上下文和 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() 的调用传递给您的可组合项。

有关示例,请参阅以下小节。

示例

为了演示前面各节,请在以下代码段中观察以下几点

  1. 图中的每个目标都是使用路由创建的,路由是描述该目标所需数据的可序列化对象或类。
  2. MyAppNavHost 可组合项持有 NavController 实例。
  3. 因此,对 navigate() 的调用应该在那里发生,而不是在较低的可组合项(如 ProfileScreen)中发生。
  4. ProfileScreen 包含一个按钮,点击该按钮可将用户导航到 FriendsList。但是,它本身不调用 navigate()
  5. 相反,该按钮调用一个作为参数 onNavigateToFriends 公开的函数。
  6. MyAppNavHostProfileScreen 添加到导航图时,它会为 onNavigateToFriends 传递一个调用 navigate(route = FriendsList) 的 lambda 表达式。
  7. 这确保了当用户按下 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/jpgimage/\* 匹配

更多上下文

本文档介绍了如何在最常见的用例中使用 NavController.navigate()。但是,该函数具有一系列重载,您可以在不同上下文中以及与任何 UI 框架一起使用这些重载。有关这些重载的更多详细信息,请参阅参考文档。

进一步阅读

有关更多信息,请参阅以下页面