导航到目的地

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() 的调用。

请参阅以下小节查看相关示例。

示例

如前面部分所示,在以下代码段中请注意以下要点:

  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()。不过,该函数有一系列过载,可供您在不同上下文中使用,以及与任何界面框架搭配使用。如需详细了解这些过载,请参阅参考文档。

深入阅读

如需了解详情,请参阅以下页面: