导航到目标

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

进一步阅读

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