使用BottomNavigationView切换标签时如何保留前一标签的页面栈状态
问题原因
默认情况下,NavigationUI 与 BottomNavigationView 绑定时,切换TAB会清空非当前TAB的导航回退栈,仅保留对应TAB的根页面,所以你从TAB1的Screen_2跳转到TAB2的Screen_3后切回TAB1,就会回到Screen_1而非保留Screen_2。
实现方案
1. 调整导航图结构
给每个TAB配置独立的嵌套子导航图,子导航图的ID需要和BottomNavigationView对应的menu item ID完全一致:
- TAB1对应子导航图,包含Screen_1、Screen_2,该子导航图ID和TAB1的menu item ID相同
- TAB2对应子导航图,包含Screen_3,该子导航图ID和TAB2的menu item ID相同
- TAB3对应子导航图,包含Screen_4,该子导航图ID和TAB3的menu item ID相同
2. 确保Navigation组件版本支持多回退栈
2.4.0及以上版本的Navigation组件原生支持多回退栈,不用额外自定义逻辑即可自动保留每个TAB的回退栈状态。请确认你的模块依赖版本不低于2.4.0,示例依赖如下:
implementation "androidx.navigation:navigation-fragment-ktx:2.7.5" implementation "androidx.navigation:navigation-ui-ktx:2.7.5"
3. 保留原有绑定逻辑,无需修改
你现有的setupWithNavController绑定代码不用调整,2.4.0+版本会默认开启多回退栈支持,切换TAB时不会清空其他TAB的回退栈。
val bottomNavigate = findViewById<BottomNavigationView>(R.id.mainButtonNavigation) val navController = (supportFragmentManager.findFragmentById(R.id.containerGuestView) as NavHostFragment).navController NavigationUI.setupWithNavController(bottomNavigate, navController)
4. 跳转逻辑适配
你当前Screen_2跳转Screen_3的全局action代码无需修改,只要全局action的目标Screen_3归属TAB2的子导航图即可,跳转后TAB1的回退栈会自动保留Screen_2的状态。
findNavController().navigate(R.id.action_global_tournamentTableGuestFragment)
异常排查
如果配置完仍不生效,请检查以下两点:
- 不要自定义重写
OnNavigationItemSelectedListener,如果有自定义点击需求,需要在回调中调用NavigationUI.onNavDestinationSelected(item, navController)来复用默认的多回退栈逻辑 - 确认NavHostFragment所在的布局标签中添加了
app:defaultNavHost="true"属性
内容的提问来源于stack exchange,提问作者Mark Glushko
相关产品推荐
相关产品推荐

