Askani
Askani

Reputation: 458

How to manage BottomNavigationView backstack in Android Navigation Component

I am using navigation component and BottomNavigationView, i am facing a problem, that is when i go to from fragment 1>2>5>4>3 and when i press back button i get fragment 1. I know this is the default behavior but i don't want this, i want to save them in backstack so when i press back button it should go to fragment 4 not 1. I have been trying and searching but i couldn't find any solution. Can i put fragment manually into backstack in kotlin?

My code:

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout
           .......................
           .......................>

            <androidx.appcompat.widget.Toolbar
               ................
               ................/>

            <fragment
                android:id="@+id/app_nav_host_fragment"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:defaultNavHost="true"
                app:navGraph="@navigation/app_nav"
                ..............
                ............../>
            <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/app_bottom_nav_view"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:background="@drawable/white_grey_border_bottom"
                app:menu="@menu/bottom_nav_menu"
                app:labelVisibilityMode="unlabeled"
                ...........
                .........../>

</androidx.constraintlayout.widget.ConstraintLayout>

app_nav.xml

<navigation 
    ...........
    ...........
    android:id="@+id/app_nav"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.instagram_clone.ui.HomeFragment"
        android:label="HomeFragment"
        tools:layout="@layout/fragment_home"/>
    .............
    .............
    .............
    .............
</navigation>

MainActivity.kt

class MainActivity : AppCompatActivity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        val binding  = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        val bottomNavView = binding.appBottomNavView
        val navController = findNavController(R.id.app_nav_host_fragment)

        bottomNavView.setupWithNavController(navController)

    }
}

Upvotes: 10

Views: 10337

Answers (2)

Vikash Kumar Tiwari
Vikash Kumar Tiwari

Reputation: 835

I used the solution provided by @ianhanniballake like using android:menuCategory="secondary" in menu item but I encountered another problem that now android system started following the navigation track. So let suppose you navigate fragments like A -> B -> C -> D -> C -> B -> A.

Now press back button B is selected and displayed, again press back button C is displayed, again press back button D is displayed, again press back button C is displayed, again press back button B is displayed, again press back button A is displayed(start destination is reached and all fragments are pooped off the stack)

If you agains press the back button then app is closed.

So solution to this problem is handle back button navigation manually in the activity where your NavController is tied by using OnBackPressedDispatcher

    onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {

            // If the current destination is not the start destination, pop the back stack
            if (navController.currentBackStackEntry?.destination?.id != navController.graph.startDestinationId) {
                navController.popBackStack()
            } else {
                // If the start destination is already reached, exit the app
                isEnabled = false
                finish()
            }
        }
    })

Upvotes: 0

ianhanniballake
ianhanniballake

Reputation: 200110

As per the documentation on onNavDestinationSelected() (the method that setupWithNavController() uses when selecting a MenuItem):

By default, the back stack will be popped back to the navigation graph's start destination. Menu items that have android:menuCategory="secondary" will not pop the back stack.

So just add android:menuCategory="secondary" to each of the menu items used with your BottomNavigationView.

Upvotes: 25

Related Questions