Facing an issue where using navController.navigate(R.id.tab_dashboard) to dynamically switch to a bottom navigation tab messes up with bottom navigation.
Attached a video to explain the issue. Video link: https://github.com/hishamMuneer/BottomNavSample/blob/master/video/bottomnav_issue.mp4 Sample code here: https://github.com/hishamMuneer/BottomNavSample.git
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
val fab = binding.fab
fab.setOnClickListener {
navController.navigate(R.id.navigation_dashboard)
}
}
}
Disclaimer: This answer targets the demonstrations why this behavior happens per OP request. @Arda Kazancı thankfully already provides the answer.
Navigating to some
BottonNavigationViewfragment using aNavControlleraction doesn't actually achieve a realBottonNavigationViewmenu item selection; instead it does a fragment transaction on the fragment placeholder, i.e., theNavHostFragment.That is because the action has just abstract information to the destination fragment whether the destination fragment is a part of
BottomNavigationView, or just a normal fragment.So, when using the action
navController.navigate(R.id.action_global_dashBoardFragment)will not make thenavView.setupWithNavController(navController)do its job, or at least will distub it.In your shared video, after hitting the fab, and then trying to hit the unsuccessful selection Home tab, that doesn't do a true selection because the
NavigationBarView.OnItemSelectedListenercallback returnsfalse(keeping the current Dashboard tab selected instead of the Home fragment).This can be demonstrated by using a wrapper around the
NavigationBarView.OnItemSelectedListenerinterface to log the returned value of theonNavigationItemSelected()callback:Use the below custom
MyBottomNavigationViewin the activity_main.xml layout instead of the<com.google.android.material.bottomnavigation.BottomNavigationView:The wrapper interface:
Now catching that log by doing the exact scenario shared in your video:
The callback returns true (i.e., it's a successful tab selection) until hitting the fab just before the last log which returns false (which is not considered a tab selection, so keep the current tab selected) which occurs when the Home tab is hit, but the Dashboard keeps on because the fab action (
R.id.action_global_dashBoardFragment) already disturbed the functionality of thenavView.setupWithNavController(navController).The answer is to never use actions with
BottomNavigationViewfragments which are automatically managed by theNavControllerwithsetupWithNavController(), but to imitate using the tab pragmatically as demonstrated by @Arda Kazancı in order to make the automation of thesetupWithNavController()apply: