Search code examples
androidbottomnavigationviewandroid-architecture-navigation

Bottom Navigation View on Backpress wrong icon


I have 3 fragment in my MainActivity with NavigationGraph and BottomNavigationView. Those fragment is HomeFragment, DashboardFragment, and NotificationFragment. The startDestination is DashboardFragment so when i launch the app it will shows DashboardFragment.

The problem occured when i press back button. Fragment show DashboardFragment but the BottomNavigationView show most right menu which is NotificationFragment. I hope to show DashboardFragment AND DashboardMenu. How to solve it?

SS

This is my code:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val view = ActivityMainBinding.inflate(layoutInflater)
    setContentView(view.root)
    
    val navController = findNavController(R.id.nav_host_fragment)
    view.navView.setOnNavigationItemSelectedListener {
        if (navController.currentDestination!!.id != it.itemId) {
            val builder = NavOptions.Builder()
                .setLaunchSingleTop(true)
            if (it.order and Menu.CATEGORY_SECONDARY == 0) {
                builder.setPopUpTo(findStartDestination(navController.graph).id, false)
            }
            val options = builder.build()
            try {
                navController.navigate(it.itemId, null, options)
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            }
        }
        true
    }
    navController.addOnDestinationChangedListener { _, destination, _ ->
        val menu = view.navView.menu
        for (i in 0 until menu.size()) {
            val item = menu[i]
            val menuId = item.itemId
            val destinationId = destination.id
            val checked = menuId == destinationId
            item.isChecked = checked
        }
    }
}

Solution

  • I'd propose changing your implementation so it uses setupWithNavController extension function from androidx.navigation.ui package.

    In activity's xml

    (...)
         <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/bottom_navigation"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:menu="@menu/bottom_navigation_menu" />
    (...)
    

    In activity

    a) declare bottomNavigation

    private val bottomNavigation: BottomNavigationView by lazy { findViewById(R.id.bottom_navigation) }
    

    b) create setup navigation function and call it in onCreate method

    private fun setupNavigation() {
            val navHostFragment =
                supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    
            val navController = navHostFragment.navController
            navController.addOnDestinationChangedListener(this)
            bottomNavigation.setupWithNavController(navController)
        }
    

    This way back button will be properly handled automatically

    PS. If you don't want fragments to be recreated on menu item reselection, then set NavigationItemReselectedListener on bottomNavigationView.