我希望大部分菜单项由导航组件的控制器处理,但我也想像这样单独处理一个"注销"菜单项:
val navController = findNavController(R.id.nav_host_fragment)
nav_view.setNavigationItemSelectedListener { item ->
when(item.itemId) {
R.id.logout_menu_item -> {
Toast.makeText(context, "Logut Menu Item Touched", Toast.LENGTH_LONG).show()
true
}
else -> false
}
}
nav_view.setupWithNavController(navController)
bottom_navigation.setupWithNavController(navController)
为什么这不起作用,以及如何解决此问题?
我不确定目前是否有适当的方法来执行此操作,但您始终可以不使用setupWithNavController
方法。
我也遇到了这个问题,作为测试,在调用setupWithNavController
之后将我的呼叫移动到setNavigationItemSelectedListener
,并且我用于注销的导航代码正在运行,但导航的其余部分没有。我认为这意味着导航侦听器在后续调用setNavigationItemSelectedListener
时被覆盖,并且setupWithNavController
调用setNavigationItemSelectedListener
内部。
我试图在谷歌源代码中验证这一点,但无法轻松找到存储库。
我通过不调用setupWithNavController
而是执行以下操作来解决此问题:
navigationDrawer?.setNavigationItemSelectedListener { menuItem ->
if (menuItem.itemId == R.id.action_sign_out) {
// sign out logic
return@setNavigationItemSelectedListener true
}
val result = menuItem.onNavDestinationSelected(navigationController)
drawerLayout?.closeDrawers()
result
}
与贾斯汀的回答类似,我从 NavigationUI 复制了侦听器设置代码,如下所示:
fun NavigationView.setupWithNavController(navController: NavController, onMenuItemSelected: (MenuItem) -> Boolean) {
NavigationUI.setupWithNavController(this, navController) // because this does more than set the nav view listener
setNavigationItemSelectedListener { item ->
if (onMenuItemSelected(item)) {
return@setNavigationItemSelectedListener true
}
NavigationUI.onNavDestinationSelected(item, navController).also {
val parent = parent
if (parent is DrawerLayout) {
parent.closeDrawer(this)
} else {
findBottomSheetBehavior()?.state = BottomSheetBehavior.STATE_HIDDEN
}
}
}
}
private fun View.findBottomSheetBehavior(): BottomSheetBehavior<*>? {
val params = layoutParams
if (params !is CoordinatorLayout.LayoutParams) {
return (parent as? View)?.findBottomSheetBehavior()
}
return params.behavior as? BottomSheetBehavior<*>
}
然后,在Activity.onCreate()
:
navigation_view.setupWithNavController(navController) { item ->
when (item.itemId) {
R.id.mySpecialFragment ->
// do something special like: navController.popBackStack(id, true)
}
false // usually still want to perform default steps
}
一个更防弹的解决方案可能涉及子类化NavigationView
和覆盖setNavigationItemSelectedListener()
,以便您可以将NavigationUI
设置的实际侦听器包装为一个包含通过某个公共setter传入的对您自己的侦听器的调用的侦听器。