How To Handle Multiple Navhosts/navcontrollers?
I'm having a problem when dealing with multiple NavHosts. This issue is very similar to the one asked here. I think the solution for this question would help me as well, but it's a
Solution 1:
As suggested by jsmyth886, this blog post pointed me to the right direction.
The trick was to findFragmentById()
to get the NavHost
directly from the fragment container (in this case, the one sharing the screen with the rest of the Master Detail screen). This allowed me to access the correct NavController
and navigate as expected.
It's important to create a second NavGraph
too.
So a quick step-by-step:
- Create the main
NavGraph
to make all the usual navigation (how it would work without the Master Detail Flow); - Create a secondary
NavGraph
containing only the possibleDestinations
that the Master Detail fragment will access. NoActions
connecting then, just theDestinations
. - In the main
<fragment>
container, set the attributes like that:
<fragment
android:id="@+id/fragmentContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/main_nav_graph"
app:defaultNavHost="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- The
app:defaultNavHost="true"
is important. Then the Master Detail layout will look like that:
<?xml version="1.0" encoding="utf-8"?><layoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rvFruits"android:layout_weight="3"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="8dp"/><FrameLayoutandroid:layout_weight="1"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/sideFragmentContainer"android:name="androidx.navigation.fragment.NavHostFragment"app:navGraph="@navigation/secondary_nav_graph"app:defaultNavHost="false"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout></LinearLayout></RelativeLayout></layout>
- Again, the attribute
app:defaultNavGraph
is important, set it to false here. - In the code part, you should have a boolean flag to verify if your app is running on a Tablet or not (the link provided in the beginning of the answer explains how to do it). In my case, I have it as a
MutableLiveData
inside myViewModel
, like that I can observe it and change layouts accordingly. - If is not tablet (i.e. follows the normal navigation flow), simply call
findNavController().navigate(R.id.your_action_id_from_detail_to_some_other_fragment)
. The main navigation will happen using the mainNavController
; - If is tablet using the Master Detail Flow, you must find the correct
NavHost
andNavController
by finding the<fragment>
that contains it, like that:
val navHostFragment = childFragmentManager.findFragmentById(R.id. sideFragmentContainer) as NavHostFragment
- And finally you can navigate to the Fragment that you want to appear dividing the screen with the rest of the Master Detail screen by calling
navHostFragment.navController.navigate(R.id.id_of_the_destination)
. Notice that here we don't callActions
, we call theDestination
directly.
That's it, simpler than what I thought. Thank you Lara Martín for the blog post and jsmyth886 for pointing me to the right direction!
Post a Comment for "How To Handle Multiple Navhosts/navcontrollers?"