NavigationUI not working correctly with bottom navigation view implementation
Asked Answered
A

5

19

So I have a scenario in which I have 5 fragments attached with bottom navigation.

1. Home 2. Inbox 3. Search 4. Notification 5. Profile

So I have another fragment called (BarcodeDetail) to which I navigate from Home Fragment.

(Home -> BarcodeDetail)

Now from BarcodeDetail I navigate to Search Fragment

(BarcodeDetail -> Search)

But now if I select Home Fragment from BottomNavigationView It did not go to Home Fragment.

Rather than it selects the same current fragment that is Search Fragment.

(The log print the name of Search Fragment)

navController.addOnDestinationChangedListener((controller, destination, bundle) -> {

            Timber.d("Destination -> %s", destination.getDisplayName());
});

private void setupBottomNavigation() {

        NavHostFragment navHostFragment = (NavHostFragment)
                getSupportFragmentManager().findFragmentById
                        (R.id.fragment_container_view);

        if (navHostFragment != null) {

            navController = navHostFragment
                    .getNavController();

            NavigationUI.setupWithNavController(
                    binding.bottomNavigation, navController);

            initDestinationListener();

        }
    }

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/sellerHomeFragment"
        android:icon="@drawable/ic_home"
        android:title="@string/home_text" />

    <item
        android:id="@+id/inboxFragment"
        android:icon="@drawable/ic_chat"
        android:title="@string/chats_text" />

    <item
        android:id="@+id/searchFragment"
        android:icon="@drawable/ic_search"
        android:title="@string/search_text" />

    <item
        android:id="@+id/sellerAlertFragment"
        android:icon="@drawable/ic_notification"
        android:title="@string/notifications_text" />

    <item
        android:id="@+id/sellerProfileFragment"
        android:icon="@drawable/ic_profile"
        android:title="@string/profile_text" />

</menu>

Please let me know if you need more information. Thanks

Archducal answered 13/1, 2022 at 21:46 Comment(3)
HI. I have an issue same to yours. How you resolve it ?Rhinoceros
@ThânHoàng below answer is almost what I have done for now!Archducal
Can you share a piece of your code about that ? I have tried but seem can not resolveRhinoceros
M
17

The navigation component lib enables multiple backstack support by default since the version 2.4.0, which has been also thoroughly demonstrated in this blog.

According to your sample code, your five top level fragments in your bottom sheet nav would now have their own backstack, the problem arises if you want to navigate from one of the top level fragments to another, like in your case (Home -> ... -> Search).

The reason why you cannot go back to Home is because you have never left Home's backstack and now Search is on top of it, i.e. the navigation component thinks that you're already on the correct fragment.

I would suggest to go through the navigation lib's recent changes first, rather then trying to quick fix as this is quite a behavior change and it could also affect other parts of your app's navigation.

Technically speaking, the way how the multiple back stacks for the bottom nav works is that every time you select a different bottom nav option, the implementation of onNavDestinationSelected(item: MenuItem, navController: NavController) would pop & save the state of all the fragments from the current top level fragment and then navigate to the other top level fragment by restoring it's state.

So, in order to "switch from one backstack to another" like in your case when you navigate from BarcodeDetail to Search, you need to adapt your current actions by at least these two options:

app:popUpTo="@id/id_of_home"
app:popUpToSaveState="true"

(where id_of_home is should be the id of Home and where I assume that this is the action with destination to Search).

With these two lines, you would pop & save the state of Home -> BarcodeDetail and navigate to Search, if you now would navigate back to Home via the bottom nav option, then you would restore the state and your navigation should be basically possible.

However, please note that you might need another flags like app:restoreState="true" and/or app:popUpToInclusive="true" depending on what you want achieve.

Megalomania answered 6/3, 2022 at 11:23 Comment(3)
Hi. Do you have any sample code for this bro ? I'm looking for a solution for this.Rhinoceros
This is a really good explanation and the actual reason of the problem after the migrating to the new Navigation version ! With the multiple back stacks introduced, we need to specify our intentions with app:popUpTo or app:popUpToSaveState in actions.Edmiston
Works for me, thx. @ThânHoàng, just add those 2 lines to your action element in your navigation.xml.Ego
S
7

First clear the backstack by using this line of code

     navController.popBackStack();

After that do navigate to your fragment by using this line of code

navController.navigate(R.id.your_fragment_id);

From this you will be able to navigate in bottom navigation without any issue.

Swob answered 14/6, 2022 at 11:24 Comment(1)
as long as google is not able to design things in a stable and logical way, this should be the accepted answer.Chauncey
U
2

I got the same problem in Navigation component 2.4.0, switching back to 2.3.5 works.

But after some testing I got it to work with 2.4.0 also if I add a listerner to BottomNavigationView and handle the navigation my self in addition to NavigationUI.setupWithNavController(..).

bottomNavigationView.setOnItemSelectedListener(item -> {
   //logic like navController.popBackStack(R.id.homeFragment, false) and navController.navigate(item.getItemId(), null, options)
   return true;
});
Uncial answered 27/1, 2022 at 14:36 Comment(0)
A
2

To Disable BackStack use the below Hacky Solution,

binding.bottomNavigationView.setOnItemSelectedListener {
            NavigationUI.onNavDestinationSelected(it,findNavController(R.id.mainNavHost))
            findNavController(R.id.mainNavHost).popBackStack(it.itemId, inclusive = false)
            true
        }

Tested with

implementation 'androidx.navigation:navigation-fragment-ktx:2.4.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.0'
Apollinaire answered 19/5, 2022 at 10:14 Comment(1)
You can get the same results by using NavigationUI.onNavDestinationSelected(item, controller, saveState = false)Officiant
S
1

i am also faced same problem just add app:popUpTo="@id/navigationHome" in your action tag

  <fragment
    android:id="@+id/navigationHome"
    android:name="com.mymedisage.medisageapp.ui.home.HomeFragment"
    android:label="@string/title_home"
    tools:layout="@layout/fragment_home_new" >
    <action
        android:id="@+id/action_homeFragment_to_communityFragment"
        app:destination="@id/navigationCommunity"
        app:popUpTo="@id/navigationHome"
        app:popUpToSaveState="true"
        />
Snipe answered 12/12, 2022 at 13:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.