androidx.navigation菜单项的多个目的地



我有一个使用androidx导航库的活动应用程序。对于其中一个菜单目的地,我实际上有一个片段作为目的地,没有任何视图,根据用户提供的配置的状态,它要么重定向到应该存在的真实目的地,要么重定向到当前两个不同视图中的一个,这两个视图告诉用户他需要首先设置配置,要么当前没有活动配置(已删除?(,他需要选择一个可用的配置。

现在,从功能上讲,这种方法非常有效。然而,由于androidx导航通过id将菜单项与目的地联系在一起,因此将您带到该视图的菜单项被从不选中,因为它与片段目的地匹配,其中没有视图。

我尝试将NavController.OnDestinationChangedListener添加到我的"活动"中,并将其添加到navControllernavController.addOnDestinationChangedListener(this)中。但之后它似乎被导航覆盖了。

override fun onDestinationChanged(controller: NavController, destination: NavDestination, arguments: Bundle?) {
val destinations = listOf(R.id.destinationA, R.id.destinationB, R.id.destinationC)
if(destinations.contains(destination.id)) {
nav_view.menu.getItem(0).isChecked = true
}
}

它被定义为右菜单项。当我将isChecked = true更改为isEnabled = false时,我无法再点击它。

同样,当我做这个奇怪的黑客它工作

GlobalScope.launch(Dispatchers.Main) {
delay(1000)
nav_view.menu.getItem(0).isChecked = true
}

不用说,这不是一个很好的解决方案。


这里的任何人都知道如何在这方面覆盖androidx导航的默认行为?

如果我找到一个合适的解决方案,我稍后会回来报告。

如果目前无法做到这一点,那么在抽屉打开时添加一个监听器并设置所选菜单项可能是一个很好的解决方法。

不要像文档中提到的那样使用setupWithNavController(),而是自己设置。

如前所述,当使用setupWithNavController()设置菜单项时,单击菜单项时会调用NavigationUI中的onNavDestinationSelected()辅助方法。所以你可以试试这样的东西:

yourNavigationView.setNavigationItemSelectedListener { item: MenuItem ->
if(item.itemId == R.id.noViewFragmentId) {
val isConfigurationProvided = ...
if(!isConfigurationProvided) {
//Perform your actions (navigate to either of the two alternate views)
return@setNavigationItemSelectedListener true
}
}
val success = NavigationUI.onNavDestinationSelected(item, navController)
if(success) {
drawerLayout.closeDrawer(GravityCompat.START)
item.isChecked = true
}

success
}

我将添加它作为一个可能的解决方案,并暂时坚持使用它。我仍然觉得应该有更好的方法来做到这一点,所以我不会接受这是一个错误。

这基本上是我在写问题时得到的想法

如果目前无法做到这一点,那么在抽屉打开时添加一个监听器并设置所选菜单项可能是一个很好的解决方法。

class SetActiveMenuDrawerListener(
private val navController: NavController,
navigationView: NavigationView) : DrawerLayout.DrawerListener {
private var checked = false
private val destinations = listOf(R.id.destinationA, R.id.destinationB, R.id.destinationC)
private val menu = navigationView.menu.getItem(0)
init {
navController.addOnDestinationChangedListener { _, _, _ -> checked = false }
}
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
}
override fun onDrawerOpened(drawerView: View) {
}
override fun onDrawerClosed(drawerView: View) {
}
override fun onDrawerStateChanged(newState: Int) {
if(checked) return
val currentDestination = navController.currentDestination ?: return
if(destinations.contains(currentDestination.id)) {
menu.isChecked = true
}
checked = true
}
}

然后将其添加到抽屉布局

drawer_layout.addDrawerListener(SetActiveMenuDrawerListener(navController, nav_view))

我确实将代码添加到了onDrawerStateChanged中,而不是onDrawerOpened中,因为如果在拖动抽屉时单击抽屉,onDrawerOpened会被调用得有点晚。

这不是最漂亮的东西,但它能完成任务。

最新更新