androidandroid-fragmentsnavigationandroid-jetpack-navigation

Android navigation graph removes on back press to much from stack


I start to use the Navigation Components library and created a graph to navigation between different fragments. My basic setup is a BottomNavigationView with two Fragments (A and B). Fragment B can go deeper inside graph to Fragment C and Fragment C goes to Fragment D. Everythings works at this point and the back stack goes from D -> C -> B.

My problem is Fragment Z which is accessible from a toolbar menu defined on the activity and used by every Fragment. What i want is a path from A -> B -> C -> D -> Z and by pressing the back button i want to go one step back to Fragment D. But i go to the start of my graph which is Fragment A.

Fragment Z uses no actions. The Navigation Component detects the same fragment.id inside navigation graph and menu.xml and does the navigation for me. So an can't define some multi back stack magic for me.

navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@id/fragmentA">

<fragment android:id="@+id/fragmentA" />

<fragment android:id="@+id/fragmentZ" />

<fragment
    android:id="@+id/fragmentB">

    <action
        android:id="@+id/action_b_to_c"
        app:destination="@id/fragmentC" />
</fragment>

<fragment
    android:id="@+id/fragmentC">

    <action
        android:id="@+id/action_c_to_d"
        app:destination="@id/fragmentD" />
</fragment>
</navigation>

toolbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/fragmentZ"
    android:title="Go to Z"
    app:showAsAction="always" />
</menu>

bottom_navigation.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
    <item
        android:id="@+id/fragmentA"
        android:title="Go to A" />
    <item
        android:id="@+id/fragmentB"
        android:title="Go to B" />
</group>
</menu>

MainActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView( R.layout.activity_main )
        val toolbar: MaterialToolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        val navController = navHostFragment.navController
        val navView: BottomNavigationView = findViewById( R.id.bottomNavigation )
        navView.setupWithNavController( navController )
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu_toolbar, menu)
        return super.onCreateOptionsMenu(menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val navController = findNavController(R.id.nav_host_fragment)
        return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
    }
}

Solution

  • NavigationUI.onNavDestinationSelected() reads:

    Also see: Navigation and the back stack.