Alex Busuioc
Alex Busuioc

Reputation: 1182

Bottom navigation bar malfunctions when navigating from a fragment

I'm using the bottom navigation bar with the navigation component

To make the two components work together I called:

bottomNavigationView.setupWithNavController(navController)

Everything works as expected except when I navigate from inside a fragment instead of the bottom navigation bar

enter image description here

"View all" opens the same fragment as "Reports" from the bottom navigation bar

binding.viewAllScansTv.setOnClickListener {
    val action = MainFragmentDirections.actionMainFragmentToReportsFragment()
    navController.navigate(action)
}

After clicking on "View all", the fragment is opened, the "Reports" button gets selected, however, navigating back "Home" does not work anymore

How can I fix this weird behavior?

The nav graph:

<navigation app:startDestination="@id/mainFragment">
    <fragment
        android:id="@+id/mainFragment"
        android:name="com.package.name.ui.main.MainFragment"
        android:label="MainFragment"> 
        <action                android:id="@+id/action_mainFragment_to_reportsFragment"
            app:destination="@id/reportsFragment" />
    </fragment>
</navigation>

The bottom navigation menu:

<menu>
    <item
        android:id="@+id/mainFragment"
        android:title="Home"/>    
    <item
        android:id="@+id/reportsFragment"
        android:title="Reports"/>
    <item
        android:id="@+id/settingsFragment"
        android:title="My account"/>
</menu>

Upvotes: 7

Views: 3688

Answers (3)

Dkathayat1
Dkathayat1

Reputation: 173

Setting a click listener on any view should have the same effect as if the user taps the corresponding item in the bottom navigation. So you need to call setSelectedItemId() on the BottomNavigationView.

val mainBottomNav =
                activity?.findViewById<BottomNavigationView>(R.id.homeBottomNavigation)
            mainBottomNav?.selectedItemId = R.id.baseHomeFragment

Upvotes: 1

Yousef Elsayed
Yousef Elsayed

Reputation: 145

Your current answer is fine but if you need to pass arguments it wont work, So use this

In the Navigation XML add these lines to the action

app:launchSingleTop="true"
app:popUpTo="@+id/main_navigation"
app:popUpToInclusive="true"

And make sure app:popUpTo="@+id/main_navigation" has the same id as your navigation xml

So the final action should look like:

     <action
            android:id="@+id/action_cameraFragment_to_searchFragment"
            app:destination="@id/searchFragment"
            app:launchSingleTop="true"
            app:popUpTo="@+id/main_navigation"
            app:popUpToInclusive="true"/>

And Navigate normally using the action

val action = CameraFragmentDirections.actionCameraFragmentToSearchFragment()
findNavController().navigate(action)

Upvotes: 6

Alex Busuioc
Alex Busuioc

Reputation: 1182

As @ianhanniballake mentioned in a comment, a similar question was posted here

What I ended up doing was replacing

val action = MainFragmentDirections.actionMainFragmentToReportsFragment()
navController.navigate(action)

with

val item = mainBottomNavigationView.menu.findItem(R.id.reportsFragment)
NavigationUI.onNavDestinationSelected(item, navController)

So basically I used the NavigationUI API to navigate so that it correctly tracks the back stack. The same NavigationUI API is being used by the BottomNavigationView internally

Upvotes: 14

Related Questions