Bottom Navigation选中项按下返回键返回基础Fragment时不更新问题
问题根因
- 你当前的
replaceFragment方法没有将Fragment事务添加到回退栈,按返回键时是系统自动弹出栈顶的Fragment,这个过程不会触发BottomNavigationView的OnItemSelectedListener回调,因此选中状态不会自动更新。 - 你尝试直接设置
selectedItemId无效,一方面是没有选对调用时机(比如只在宿主onViewCreated执行一次,回退操作不会重新触发),另一方面直接设置这个属性会触发选中监听回调,反而会引发多余的Fragment替换操作。
修复步骤
1. 修改Fragment事务逻辑,添加回退栈标记
修改replaceFragment方法,给不同Fragment添加对应的标识,同时将非首页的事务加入回退栈,避免按返回键直接退出应用:
// 回退栈监听存为成员变量,后续销毁时移除避免内存泄漏 private var backStackListener: FragmentManager.OnBackStackChangedListener? = null private fun replaceFragment(fragment: Fragment, tag: String){ val transaction = activity?.supportFragmentManager?.beginTransaction() transaction?.replace(R.id.frameLayout,fragment, tag) // 非首页事务加入回退栈 if(tag != "main"){ transaction?.addToBackStack(tag) } transaction?.commit() }
调整底部导航选中监听的调用逻辑:
binding.bottomNavigationView.setOnItemSelectedListener { when(it.itemId){ R.id.nav_profile -> { replaceFragment(ProfileFragment(), "profile") } R.id.nav_mainpage -> { // 点击首页时清空回退栈,避免层级冗余 activity?.supportFragmentManager?.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) replaceFragment(MainPageFragment(), "main") } } return@setOnItemSelectedListener true } // 初始化加载首页 replaceFragment(MainPageFragment(), "main")
2. 监听回退栈变化,同步更新底部导航选中状态
在宿主Fragment的onViewCreated中添加回退栈监听,每次栈变化时根据当前显示的Fragment修改导航栏选中状态,这个方式不会触发选中监听回调,不会引发多余事务:
backStackListener = FragmentManager.OnBackStackChangedListener { val currentFragment = activity?.supportFragmentManager?.findFragmentById(R.id.frameLayout) when(currentFragment?.tag){ "main" -> binding.bottomNavigationView.menu.findItem(R.id.nav_mainpage).isChecked = true "profile" -> binding.bottomNavigationView.menu.findItem(R.id.nav_profile).isChecked = true } } activity?.supportFragmentManager?.addOnBackStackChangedListener(backStackListener!!)
在宿主销毁时移除监听:
override fun onDestroyView() { backStackListener?.let { activity?.supportFragmentManager?.removeOnBackStackChangedListener(it) } super.onDestroyView() }
内容的提问来源于stack exchange,提问作者Tunahan
相关产品推荐
相关产品推荐

