I have a navigation graph consisting of 3 nested graphs. Something like this:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_graph"
app:startDestination="@id/nav_main">
<navigation android:id="@+id/nav_main"
app:startDestination="@id/mainFragment" ...>
<navigation android:id="@+id/nav_second" ...>
<navigation android:id="@+id/nav_third" ...>
I am using a NavigationView (in a DrawerLayout) to navigate between them. The application starts in nav_main, and as desired the NavigationView can be used to switch back and forth between nav_main, nav_second, nav_third. As desired the navigation framework creates a backstack for each of the nested trees, and when switching between them using the NavigationView they are restored to the correct fragment and state.
One thing I have observed is that the nav_second and nav_third backstacks always have on them the first screen of the application. Specifically, this would be the startDestination fragment of the nested tree identified as the navigation graph startDestination, aka mainFragment in the example above. My understanding from reading online is that this is expected.
This however does cause an undesirable behavior of the back button. If you are in nav_second or nav_third and you hit the back button to unroll their stacks the entire way, you end up getting to the mainFragment at the top of the stack. This mainFragment is not the one that lives in the nav_main backstack. It is a duplicate with its own state. The user is not brought back to the location in nav_main where they left. They can restore their spot in nav_main by selecting it again from the NavigationView. This behavior is rather confusing to users.
Ideally hitting the back button from nav_second or nav_third should restore the backstack for nav_menu with the user going back to the point they departed it from.
I have been able to achieve the desired behavior by intercepting the back button and using a custom actions, as such:
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
Navigation.findNavController(view).navigate(R.id.myaction);
}
});
Which action defined by:
<action
android:id="@+id/myaction"
app:destination="@id/nav_main"
app:popUpTo="@id/mainFragment"
app:restoreState="true"
app:popUpToSaveState="true"/>
While as far as I can tell this achieve the desired behavior, I don't like that I need to do this at all. Is there a better way to achieve this? The default behavior seems like an odd choice. Is this what others have observed (and not something we have somehow introduced in our app)? Thanks