Reputation: 1941
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?
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
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
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
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