防止导航到同一片段

时间:2019-10-02 23:17:08

标签: android kotlin android-jetpack android-jetpack-navigation

我正在将Android导航jetpack库与BottomNavigationView一起使用。我已经实现了NavHost,NavGraph和片段。当我使用动作进行导航时,一切都按预期进行。

我使用以下代码设置所有内容:

 val navController = Navigation.findNavController(this, R.id.nav_host)
 bottom_navigation.setupWithNavController(navController)

问题是,如果我单击选项卡2次,则片段将被重新创建两次。有没有办法拦截导航?我不想导航到所显示的相同片段。

3 个答案:

答案 0 :(得分:4)

根据this issue

  

可以随意设置OnNavigationItemReselectedListener,它优先于NavigationUI设置的OnNavigationItemSelectedListener

val navController = Navigation.findNavController(this, R.id.nav_host)
bottom_navigation.setupWithNavController(navController)
bottom_navigation.setOnNavigationItemReselectedListener {
  // Do nothing to ignore the reselection
}

答案 1 :(得分:0)

我写了这个扩展名。它将检查带有目标的当前片段,如果两者相同,则将仅关闭抽屉。但是关闭抽屉时存在一些动画问题。

fun NavigationView.setupWithUniqueFragment(navController: NavController) {

    this.setNavigationItemSelectedListener(object : NavigationView.OnNavigationItemSelectedListener {
        override fun onNavigationItemSelected(item: MenuItem): Boolean {
            val parent = this@setupWithUniqueFragment.parent
            if (item.itemId == navController.currentDestination?.id) {
                if (parent is DrawerLayout) {
                    parent.closeDrawer(this@setupWithUniqueFragment, true)
                }
                return true
            }
            val handled = NavigationUI.onNavDestinationSelected(item, navController)
            if (handled) {
                if (parent is DrawerLayout) {
                    parent.closeDrawer(this@setupWithUniqueFragment, true)
                }
            }
            return handled
        }

    })

    val weakReference = WeakReference<NavigationView>(this@setupWithUniqueFragment)
    navController.addOnDestinationChangedListener(
        object : NavController.OnDestinationChangedListener {
            override fun onDestinationChanged(
                controller: NavController,
                destination: NavDestination, arguments: Bundle?
            ) {
                val view = weakReference.get()
                if (view == null) {
                    navController.removeOnDestinationChangedListener(this)
                    return
                }
                val menu = view.menu
                var h = 0
                val size = menu.size()
                while (h < size) {
                    val item = menu.getItem(h)
                    item.isChecked = matchDestination(destination, item.itemId)
                    h++
                }
            }
        })
}

internal fun matchDestination(
    destination: NavDestination,
    @IdRes destId: Int
): Boolean {
    var currentDestination: NavDestination? = destination
    while (currentDestination!!.id != destId && currentDestination.parent != null) {
        currentDestination = currentDestination.parent
    }
    return currentDestination.id == destId
}

答案 2 :(得分:0)

在使用“关于”页面(使用非常好的AboutLibraries)时,我遇到了同样的问题,它将堆积重复的页面。我最终在OnOptionsItemSelected方法中完成了此操作

            case R.id.action_about:
            NavController navController = Navigation.findNavController( this, R.id.nav_host_fragment );
            if ( navController.getCurrentDestination().getId() != R.id.nav_about )
            {
                navController.navigate( R.id.nav_about );
            }

现在它仅显示一个片段,而不会在顶部堆叠相同的片段。可惜这种行为无法在XML中定义,我需要在代码中完成。