zihadrizkyef
zihadrizkyef

Reputation: 1941

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
        }
    }
}

Upvotes: 1

Views: 860

Answers (3)

Almaz_KhR
Almaz_KhR

Reputation: 541

Init navController like field of activity:

 val navController by lazy { findNavController(R.id.nav_host_fragment) }

In activity onCreate to init bottom nav:

bottom_nav?.setupWithNavController(navController)

On your activity override this fun (for correct of back button):

 override fun onSupportNavigateUp(): Boolean {
    return navController.navigateUp()
 }

Add the same names in menu file and fragment ids in nav graph. Must work

Also, if U what to use navController in your fragment to navigate somewhere:

protected lateinit var rootActivity: MainActivity
<...>
override fun onAttach(context: Context) {
    super.onAttach(context)
    rootActivity = activity as MainActivity
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   btn_action.setOnClickListener {    
       rootActivity.navController.navigate(R.id.action_id)
   }
}

action_id is id of action which U write in nav graph

Also, delete all your listeners from onCreate()

Upvotes: 1

Mieszko Koźma
Mieszko Koźma

Reputation: 634

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.

Upvotes: 2

Matrix
Matrix

Reputation: 581

try add this to the activity:

override fun onBackPressed() {
    super.onBackPressed()
    navView.setSelectedItemId(R.id.menu_dashbord)
    //jump to dashbord fragment
}

Upvotes: 1

Related Questions