I have one case and wish to implement it by arch navigation component. For example I have 2 Nav Graphs (main and nested). Can I call main graph from nested and how?
In the Project window, right-click on the res directory and select New > Android Resource File. The New Resource File dialog appears. Type a name in the File name field, such as "nav_graph". Select Navigation from the Resource type drop-down list, and then click OK.
When navigating back to destination A, we also popUpTo A, which means that we remove B and C from the stack while navigating. With app:popUpToInclusive="true" , we also pop that first A off of the stack, effectively clearing it.
NavGraph is a collection of NavDestination nodes fetchable by ID. A NavGraph serves as a 'virtual' destination: while the NavGraph itself will not appear on the back stack, navigating to the NavGraph will cause the starting destination to be added to the back stack.
The point is to get the right NavController
to navigate in the right graph. Let's take this scenario as an example:
MainActivity |- MainNavHost |- NavBarFragment | |- NestedNavHost | | |-NestedContentFragment1 | | |-NestedContentFragment2 | | | |- BottomNavigationView | |- LoginFragment
The main graph and the nested graph are in separate xml files: this is required, as far as I understood, because the navigations target different layout areas, so they require two different NavHost
s. Each Navhost
will need to reference its graph by id, which requires them to be in different resource files.
The point is that to navigate in a specific graph, we must get a reference to the right graph's owner: to do this, when calling Navigation.findNavController(view)
, the view
argument is crucial.
Docs say that
NavHostFragments register their navigation controller at the root of their view subtree such that any descendant can obtain the controller instance through the Navigation helper class's methods
So for example, if inside NavBarFragment
we write
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { navController = Navigation.findNavController(view) }
here view
is a parent of the NestedNavHost
(that is the nested NavHostFragment
), not a descendant, meaning that findNavController
will search upstream in the tree and will return the MainNavHost
's NavController
.
If instead we write
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val nestedNavHostFragment = childFragmentManager.findFragmentById(R.id.nestedNavHostFragment) as? NavHostFragment navController = nestedNavHostFragment?.navController }
where nestedNavHostFragment
is the id of the FragmentContainerView
in the layout, we get a reference to the correct NestedNavHost
. Note the use of childFragmentManager
, not parentFragmentManager
.
In case you're still using the deprecated xml <fragment>
tag, you can write
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val fragmentContainer = view.findViewById<View>(R.id.nestedNavHostFragment) navController = Navigation.findNavController(fragmentContainer) }
where nestedNavHostFragment
is the id of the <fragment>
tag. We get a reference to the correct NestedNavHost
now, because the view we pass to findNavController
belongs to the NestedNavHost
's subtree.
Similarly, if you need to get a reference to the main NavController
from inside a NestedContentFragment
, here's what we can do:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { // we can get the innermost NavController using this view, // because we are inside its subtree: nestedNavController = Navigation.findNavController(view) // we can find the outer NavController passing the owning Activity // and the id of a view associated to that NavController, // for example the NavHostFragment id: mainNavController = Navigation.findNavController(activity!!, R.id.mainNavHostFragment) }
Actually you could use Global actions to navigate from a nested nav graph destination to a main nav graph destination.
Create a global action from nested nav graph to desired destination in main nav graph (highlighted in the image below)
example:
<navigation android:id="@+id/main_nav_graph" ... > <fragment android:id="@+id/fragStart" .../> <fragment .../> <fragment .../> <navigation android:id="@+id/nested_nav_graph"> ... <!-- Global Action --> <action android:id="@+id/action_global_start" app:destination="@id/fragStart" /> </navigation> </navigation>
To navigate to main graph destination use
findNavController().navigate(R.id.action_global_start)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With