导航到目标

导航组件提供了一种直接且通用的方式来导航到目标。此接口支持多种上下文和 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() 的调用作为参数传递给您的可组合项。

请参阅以下小节,了解相关示例。

示例

作为前面几节的演示,请注意以下代码片段中的这些要点

  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 框架配合使用。有关这些重载的更多详细信息,请参阅参考文档。

延伸阅读

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