How to handle BottomNavBar menu listener with Navigation architecture component

81 Views Asked by At

In my recent project, I'm using Navigation component with BottomNavBar. BottomNavBar has 4 menus. For the first 3 menus, I've defined fragments in NavGraph file, but for the last menu item, I've to open Drawer.

Now click listener for the first 3 menus is working fine as all three fragments are opening. But I'm not able to open drawer.

enter image description here

And here is the code

private fun initNavigation() {
    val host : NavHostFragment = supportFragmentManager
        .findFragmentById(R.id.nav_host_fragment) as NavHostFragment? ?: return

    binding.bottomNav.setupWithNavController(host.navController)
}

I've also tried adding NavigationItemSelectedListener like this but app lost in handling backStack. As by pressing back button, All previously opened fragments were coming again and again.

binding.bottomNav.setOnNavigationItemSelectedListener {
        when(it.itemId){
            R.id.homeFragment->{
                navController.navigate(R.id.homeFragment)
                true
            }
            R.id.latestFragment->{
                navController.navigate(R.id.latestFragment)
                true
            }
            R.id.cartFragment->{
                navController.navigate(R.id.cartFragment)
                true
            }
            else->{
                binding.drawerLayout.openDrawer(GravityCompat.START)
                false //Don't want to check more menu item
            }
        }
    }

Please anyone suggest any idea.

2

There are 2 best solutions below

0
On

Finally came to this solution, however still waiting for the more optimized solution.

private fun setupBottomNavMenu(navController: NavController) {

    binding.bottomNav.setOnNavigationItemSelectedListener {
        when(it.itemId){
            R.id.homeFragment->{
                navController.popBackStack(R.id.homeFragment, true)
                navController.navigate(R.id.homeFragment)
                true
            }
            R.id.latestFragment->{
                navController.popBackStack(R.id.homeFragment, false)
                navController.navigate(R.id.latestFragment)
                true
            }
            R.id.cartFragment->{
                navController.popBackStack(R.id.homeFragment, false)
                navController.navigate(R.id.cartFragment)
                true
            }
            else->{
                binding.drawerLayout.openDrawer(GravityCompat.START)
                false //Don't want to check more menu item
            }
        }
    }
}

Also had need to explicitly check menu items.

private fun observeNavElements() {
    navController.addOnDestinationChangedListener { _, destination, _ ->
        when (destination.id) {
            R.id.homeFragment -> binding.bottomNav.menu.findItem(R.id.homeFragment).isChecked = true
            R.id.latestFragment -> binding.bottomNav.menu.findItem(R.id.latestFragment).isChecked = true
            else -> binding.bottomNav.menu.findItem(R.id.cartFragment).isChecked = true
        }
    }
}
1
On

Does your updated code open navigation drawer now? What I can see is that you don’t specify the itemId for the navigation drawer but rather it is handled in the else block.

binding.bottomNav.setOnNavigationItemSelectedListener {
        when(it.itemId){
            R.id.homeFragment->{
                navController.popBackStack(R.id.homeFragment, true)
                navController.navigate(R.id.homeFragment)
                true
            }
            R.id.latestFragment->{
                navController.popBackStack(R.id.homeFragment, false)
                navController.navigate(R.id.latestFragment)
                true
            }
            R.id.cartFragment->{
                navController.popBackStack(R.id.homeFragment, false)
                navController.navigate(R.id.cartFragment)
                true
            }
            R.id.navigationDrawer->{ // << HERE
                binding.drawerLayout.openDrawer(GravityCompat.START)
                false //Don't want to check more menu item
            }
        }
    }