重新选择底部导航选项卡后Android清除后退堆栈

Eve*_*lyn 11 android android-navigation bottomnavigationview android-bottomnav android-architecture-navigation

将最新的导航组件与 一起使用BottomNavigationViewNavController现在默认保存和恢复选项卡的状态:

作为此更改的一部分,onNavDestinationSelected()、BottomNavigationView.setupWithNavController() 和 NavigationView.setupWithNavController() 的 NavigationUI 方法现在会自动保存和恢复弹出目的地的状态,从而无需更改任何代码即可支持多个返回堆栈。当使用带有片段的导航时,这是与多个返回堆栈集成的推荐方法。

这很棒!现在,切换选项卡将为您提供最后查看的堆栈。

但是,如果用户重新选择一个选项卡,假设他们已经离开Home -> Detail Page A -> Detail Page B,然后他们选择Home希望返回到默认视图的选项卡,他们仍然会看到Detail Page B

似乎讨论的一部分是处理问题跟踪器中提到的“重新选择选项卡”行为,但我无法找出实现此目的的推荐方法。

NavigationAdvancedSample中包含的所有内容是:

val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)

// Setup the ActionBar with navController and 3 top level destinations
appBarConfiguration = AppBarConfiguration(
        setOf(R.id.titleScreen, R.id.leaderboard,  R.id.register)
    )
setupActionBarWithNavController(navController, appBarConfiguration)
Run Code Online (Sandbox Code Playgroud)

这只是恢复之前的状态,如发行说明中所述。

我们如何检查是否再次点击导航栏项目并清除后堆栈?

ian*_*ake 17

BottomNavigationView有自己的处理重新选择的方法setOnItemReselectedListener()(或者,当使用早期版本的材料设计库时,现在已弃用setOnNavigationItemReselectedListener())。

bottomNavigationView.setupWithNavController不设置此侦听器(因为没有具体说明重新选择选项卡应该执行的操作的材质规范),因此您需要自己设置它:

val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)

// Add your own reselected listener
bottomNavigationView.setOnItemReselectedListener { item ->
    // Pop everything up to the reselected item
    val reselectedDestinationId = item.itemId
    navController.popBackStack(reselectedDestinationId, inclusive = false)
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。当用户选择新选项卡时是否可以达到相同的效果?事实上,在新的导航版本 2.4.0 中,每个选项卡的返回堆栈都会被保存。现在我想在离开每个选项卡时重置它的后退堆栈。提前致谢 (3认同)
  • 你好,抱歉,这个解决方案对我不起作用。它仅适用于主选项卡,不适用于其他选项卡。 (2认同)

小智 12

被接受的答案让我开始朝着正确的方向前进。然而,随着 Android 导航库 2.4.0 中支持的多个 backstacks 的添加,这最终对我有用:

val currentRootFragment = supportFragmentManager.findFragmentById(R.id.main_fragment)
val navHost = currentRootFragment as? NavHostFragment
val selectedMenuItemNavGraph = navHost?.navController?.graph?.findNode(menuItem.itemId) as? NavGraph?
selectedMenuItemNavGraph?.let { menuGraph ->
             navHost?.navController?.popBackStack(menuGraph.startDestinationId, false)
}
Run Code Online (Sandbox Code Playgroud)


Wil*_*ute 8

有两种方法可以解决这个问题......

  1. 要在选择项目后更新选择(带有后退堆栈的项目,最新版本 - 2.4.2,当顶部目标中存在后退堆栈时,选择该项目不会首先选择该项目)。

    NavigationBarView.setOnItemSelectedListener {}

  2. 等待第二次单击并执行返回堆栈的弹出。

    NavigationBarView.setOnItemReselectedListener {}

最终代码是,

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment?
    val navController = navHostFragment?.navController

    mainBinding?.bottomNavigation?.apply {
        navController?.let { navController ->
            NavigationUI.setupWithNavController(
                this,
                navController
            )
            setOnItemSelectedListener { item ->
                NavigationUI.onNavDestinationSelected(item, navController)
                true
            }
            setOnItemReselectedListener {
                navController.popBackStack(destinationId = it.itemId, inclusive = false)
            }
        }
Run Code Online (Sandbox Code Playgroud)

}

希望这会有所帮助..

  • 伙计,你是最棒的。保存了我的项目! (2认同)