是否近期不推荐使用Navigation Component?Android底部导航实现咨询
方案建议
场景1:仅需要平级底部Tab高频切换,无复杂嵌套导航需求
这种场景优先推荐使用FragmentManager搭配show/hide实现,优势非常明确:
- 从根源解决视图状态丢失问题:不同于
NavController默认用replace()切换Fragment会销毁旧Fragment视图实例,show/hide仅控制Fragment的可见性,切换回原有Tab时可以直接复用已创建的视图,滚动位置、输入内容、列表加载状态全部自动保留,不需要手动做状态存储恢复。 - 切换性能更高:高频切换Tab时不需要反复执行
onCreateView/onDestroyView生命周期,流畅度更好。
你提到的自行实现过渡逻辑难度高的问题,可以通过FragmentTransaction自带的动画API直接解决,参考实现代码如下:
// 记录当前显示的Fragment实例 private var currentVisibleFragment: Fragment? = null private val navItemSelectListener = BottomNavigationView.OnNavigationItemSelectedListener { menuItem -> val targetTag = when(menuItem.itemId) { R.id.tab_home -> "TAG_HOME" R.id.tab_dashboard -> "TAG_DASHBOARD" R.id.tab_mine -> "TAG_MINE" else -> return@OnNavigationItemSelectedListener false } val fm = supportFragmentManager val ft = fm.beginTransaction() // 隐藏当前正在显示的Fragment currentVisibleFragment?.let { ft.hide(it) } // 查找目标Fragment,不存在则新建添加 var targetFragment = fm.findFragmentByTag(targetTag) if (targetFragment == null) { targetFragment = when(targetTag) { "TAG_HOME" -> HomeFragment() "TAG_DASHBOARD" -> DashboardFragment() "TAG_MINE" -> MineFragment() else -> HomeFragment() } ft.add(R.id.fragment_container, targetFragment, targetTag) } else { ft.show(targetFragment) } // 配置自定义切换动画,对应res/anim下的动画XML文件 ft.setCustomAnimations( R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right ) ft.setReorderingAllowed(true) ft.commitNowAllowingStateLoss() currentVisibleFragment = targetFragment true }
如果需要支持Tab独立返回栈,自己给每个Tab维护一个Fragment栈结构即可,逻辑完全可控,没有NavController的各种黑盒问题。
场景2:后续有嵌套导航、深层链接跳转、跨模块导航需求
如果你的应用导航逻辑比较复杂,也不需要完全放弃JetPack Navigation,可以通过自定义FragmentNavigator的方式,把默认的replace()逻辑改成show/hide,同时保留Navigation组件的其他能力,不需要完全自己从零实现所有导航逻辑。
内容的提问来源于stack exchange,提问作者ybybyb
相关产品推荐
相关产品推荐

