【问题标题】:How to handle popping back multiple screens with Jetpack Compose Navigation如何使用 Jetpack Compose Navigation 处理弹出多个屏幕
【发布时间】:2021-05-01 12:12:27
【问题描述】:

我会尝试做一些 ASCII 艺术来描述这个问题:

       <--------------------------------------\
DestinationA --> DestinationC ---------> DestinationE
DestinationB ------/    \-----> DestinationD --/

我希望这是可以理解的。 C 可以从目的地 A 和 B 到达。E 可以从 C 和 D 到达。E 返回到 A 或 B(无论哪个在后堆栈中)。目的地 C、D 和 E 接受一个参数 (id)。

实现这一点的最佳方法是什么?使用嵌套导航图似乎是可能的。

以下内容有效,但感觉更像是一种变通方法,而不是导航组件的预期工作方式。

val destination = navController.getBackStackEntry("DestinationC/{id}").destination
navController.popBackStack(destination.id, true)

目前使用NavHost是:

val navController = rememberNavController()
NavHost(navController = navController, startDestination = "DestinationA") {
    compose("DestinationA") {
        ScreenA(hiltNavGraphViewModel(it))
    }
    compose("DestinationB") {
        ScreenB(hiltNavGraphViewModel(it))
    }
    compose("DestinationC/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) {
        val viewModel = hiltNavGraphViewModel(it)
        val id = it.arguments?.getString("id")
        viewModel.setId(id)
        ScreenC(viewModel)
    }
    compose("DestinationD/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) {
        val viewModel = hiltNavGraphViewModel(it)
        val id = it.arguments?.getString("id")
        viewModel.setId(id)
        ScreenD(viewModel)
    }
    compose("DestinationE/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) {
        val viewModel = hiltNavGraphViewModel(it)
        val id = it.arguments?.getString("id")
        viewModel.setId(id)
        ScreenE(viewModel)
    }
}

【问题讨论】:

  • DestinationA & DestinationB 应该是两个不同的 startDestination ?如果是,那么使用了什么组件 bottomNav、Tabs 或其他什么?
  • 我承认对导航的理解不是很深。也许DestinationADestinationB 应该不同startDestination,但它们不是。我有一个公寓NavHost,里面有所有的目的地,DestinationAstartDestination。我正在使用导航抽屉。这会改变我应该如何设计导航吗?如果是这样,怎么做?谢谢。
  • 能否请您发布您当前的导航图以及 SS 也会有所帮助。 DestinationA & DestinationB 属于哪里?它们是抽屉的方向物品吗?
  • 是的,DestinationA 和 DestinationB 是抽屉中的顶级目的地。导航图完全无趣。我将编辑问题以使其格式正确。

标签: android android-jetpack-compose android-jetpack-navigation


【解决方案1】:

@rofie-sagara 的回答对我不起作用。有一个支持路线的导航扩展。我认为嵌套导航是一个不相关的话题。文档并没有真正解释为什么嵌套导航实际上很有用。我从 E 移回 A 或 B 的最终解决方案是:

navigation.popBackStack(route = "DestinationC/{id}", inclusive = true)

【讨论】:

  • 这个解决方案适合我
【解决方案2】:

使用嵌套导航图在差异导航上制作 DestinationCDestinationE

val navController = rememberNavController()
NavHost(navController = navController, startDestination = "DestinationA") {
    compose("DestinationA") {
        ScreenA(hiltNavGraphViewModel(it))
    }
    compose("DestinationB") {
        ScreenB(hiltNavGraphViewModel(it))
    }
    navigation("DestinationC".plus("/{id}"), "DestinationC".plus("_Route")) {
      compose("DestinationC/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) {
          val viewModel = hiltNavGraphViewModel(it)
          val id = it.arguments?.getString("id")
          viewModel.setId(id)
          ScreenC(ViewModel)
      }
    }
    compose("DestinationD/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) {
        val viewModel = hiltNavGraphViewModel(it)
        val id = it.arguments?.getString("id")
        viewModel.setId(id)
        ScreenD(viewModel)
    }
    navigation("DestinationE".plus("/{id}"), "DestinationE".plus("_Route")) {
      compose("DestinationE/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) {
          val viewModel = hiltNavGraphViewModel(it)
          val id = it.arguments?.getString("id")
          viewModel.setId(id)
          ScreenE(ViewModel)
      }
   }
}

您想从 C 移动到 E 和 popUpTo A 的示例。

navController.navigate("DestinationE".plus("/${data.id}")) {
                        popUpTo("DestinationA") {
                            inclusive = false
                        }
                    }

【讨论】:

  • 你能解释一下吗?导航代码是什么样的?
  • 从 DestinationE,我想弹回 A 或 B,以堆栈中的那个为准。在导航到 DestinationE 时,我不想将 DestinationC 从堆栈中弹出,因为您仍然应该能够从 E 导航回 C。
  • popUpTo DestinationA 会跳过 DestinationC​​pan>
  • 如果 DestinationA 不在后台怎么办?不能保证是这样。这就是我的观点。
  • 这个解决方案错过了我的问题的重点。导航可以到达堆栈中的 B 并到达 E,但不能到达 A。在这种情况下,popUpTo("DestinationA") 失败。另外,我不想在导航到 E 时从堆栈中删除 C,因为应该可以返回到 C。谢谢您的回答。也许它对尝试做你提到的事情的人有用。
猜你喜欢
  • 2022-11-07
  • 2021-10-27
  • 1970-01-01
  • 2023-02-21
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 2023-01-05
  • 1970-01-01
相关资源
最近更新 更多