如何阻止绑定Navigation Component的BottomNavigationView点击时切换导航目的地
实现方案
Navigation Component 没有提供可返回布尔值控制是否继续导航的目的地切换拦截回调,你可以通过自定义 BottomNavigationView 的选中监听器实现需求,步骤如下:
步骤1:替换默认选中监听器
默认调用NavigationUI.setupWithNavController()方法时,系统会自动给 BottomNavigationView 设置内置的选中监听器,直接执行导航逻辑。我们需要覆写这个监听器,先做自定义校验再执行导航:
bottomNavigationView.setOnItemSelectedListener { menuItem -> val targetDestId = menuItem.itemId // 自定义权限校验逻辑 if (isRequireLogin(targetDestId) && !isUserLogin()) { // 未满足跳转条件,弹出提示,不切换页面 showLoginDialog() return@setOnItemSelectedListener false } // 校验通过,执行默认导航逻辑 NavigationUI.onNavDestinationSelected(menuItem, findNavController(R.id.nav_host_fragment)) true }
这里的NavigationUI.onNavDestinationSelected()就是默认绑定逻辑里的核心导航方法,校验通过后调用即可复用原有导航逻辑。
步骤2:补充同步逻辑
为了保证导航状态和 BottomNavigationView 选中状态同步(比如按返回键回到前一个页面时,底部导航选中状态自动对应),需要额外添加目的地变化监听器:
findNavController(R.id.nav_host_fragment).addOnDestinationChangedListener { _, destination, _ -> bottomNavigationView.menu.findItem(destination.id)?.run { isChecked = true } }
辅助逻辑说明
isRequireLogin(Int):自行实现,判断目标目的地id是否属于需要登录的权限集合,你可以提前把所有需要登录的destination id存在一个Set里做匹配isUserLogin():自行实现,返回当前用户的登录状态showLoginDialog():自行实现,弹出未登录提示的弹窗逻辑
注意事项
- 如果你已经调用了
setupWithNavController()方法,必须在该方法之后覆写setOnItemSelectedListener,否则自定义监听器会被默认逻辑覆盖 - 如果你的导航图使用了嵌套导航,需要把嵌套导航的起始目的地id也加入权限校验集合,避免跳转嵌套导航时漏校验
内容的提问来源于stack exchange,提问作者Ahmad Hamwi
相关产品推荐
相关产品推荐

