Fragment Navigation should be after Modal Drawer Animation is finished
When a menu item is selected on the opening Navigation Drawer ( Modal Drawer ), Drawer closure is started with dragging animation to the left. With this, Fragment for selected item is also instantly transacted on the Main-Thread.
That Fragment Transaction disturbs Drawer Closure Animation and gives Bad User Experience.
I want to suggest that the Fragment Navigation should be after Drawer Closure for smooth animation.
You're absolutely right — triggering a fragment navigation immediately when a navigation drawer item is tapped can interrupt the drawer's closing animation, leading to a janky UI experience.
Goal Wait for the drawer closing animation to complete, and then navigate to the new fragment.
Recommended Solution Use a DrawerListener and delay navigation until the drawer is completely closed:
binding.drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener { override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
override fun onDrawerOpened(drawerView: View) {}
override fun onDrawerClosed(drawerView: View) {
// Navigate here
findNavController(R.id.nav_host_fragment).navigate(R.id.yourFragment)
binding.drawerLayout.removeDrawerListener(this) // Clean up
}
override fun onDrawerStateChanged(newState: Int) {}
}) And in your menu item click:
binding.navView.setNavigationItemSelectedListener { menuItem -> // Close drawer first binding.drawerLayout.closeDrawer(GravityCompat.START)
// Save destination ID for later use
selectedDestinationId = when (menuItem.itemId) {
R.id.nav_home -> R.id.homeFragment
R.id.nav_settings -> R.id.settingsFragment
else -> null
}
true
} Then modify the onDrawerClosed() to use that selectedDestinationId.
Better Approach with NavController (Single Source of Truth) To avoid multiple listeners and leaks, you could create a wrapper method:
private fun navigateAfterDrawerClose(@IdRes destinationId: Int) { binding.drawerLayout.addDrawerListener(object : DrawerLayout.SimpleDrawerListener() { override fun onDrawerClosed(drawerView: View) { findNavController(R.id.nav_host_fragment).navigate(destinationId) binding.drawerLayout.removeDrawerListener(this) } }) binding.drawerLayout.closeDrawer(GravityCompat.START) } Then call it cleanly:
binding.navView.setNavigationItemSelectedListener { navigateAfterDrawerClose(R.id.settingsFragment) true } Result This ensures the drawer closes fully with a smooth animation and only then performs the fragment transaction — giving your users a seamless experience.