Abhimanyu
Abhimanyu

Reputation: 14817

Prevent circular navigation logic in BottomNavigationView using Navigation component

I have a BottomNavigationView hooked up to 3 fragments (A, B and C) via the Navigation component. I also have a login fragment, which I am popping off the stack after successful login.

Observed navigation behavior:

A > B > C > A > B > C > B > Back > C > Back > B > Back > A > Back > Exit

Expected behavior:

(after reading comments of @ianhanniballake and Principles of navigation)

A > B > C > A > B > C > B > Back > A > Back > Exit

My problem is similar to circular navigation logic, but I have it in the BottomNavigationView. How to achieve my expected behavior?

main_nav.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_nav"
    app:startDestination="@id/login_fragment">

    <fragment
        android:id="@+id/login_fragment"
        android:name="com.example.app.LoginFragment"
        android:label="Login">

        <action
            android:id="@+id/login_action"
            app:destination="@id/home_fragment"
            app:launchSingleTop="true"
            app:popUpTo="@id/main_nav"
            app:popUpToInclusive="true" />

    </fragment>

    <!-- Fragments A, B and C tied to BottomNavigationView-->

</navigation>

BottomNavigationView setup

navController = findNavController(R.id.main_nav_host)
mainActivityBinding.bottomNavView.setupWithNavController(navController)

Upvotes: 0

Views: 1963

Answers (1)

user11566289
user11566289

Reputation:

In this case, you'll want to set up your login flow as a nested graph inside your main navigation graph.

Your start destination should be assigned to one of the 3 fragments hooked up to your BottomNavigationView so that pressing Back takes the user to this screen before exiting the app.

In your HomeFragment (the start destination), you can check if the user is logged in, and navigate to the nested login graph if needed.

HomeFragment.kt

if (!isLoggedIn) {
    val action = HomeFragmentDirections.showLogin()
    findNavController().navigate(action)
} else {
    // show bottom nav
}

You'll have to handle hiding/showing the BottomNavigationView as needed.

Your updated navigation graph will look like this:

main_nav.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_nav"
    app:startDestination="@id/home">

    <fragment
        android:id="@+id/home"
        android:name="com.example.app.HomeFragment"
        android:label="Home">

        <action
            android:id="@+id/show_login"
            app:destination="@id/login_nav"/>

    </fragment>

    <!-- Fragments B and C -->

    <include app:graph="@navigation/login_nav"/>

</navigation>

Upvotes: 1

Related Questions