Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
293 views
in Technique[技术] by (71.8m points)

android - New navigation component from arch with nested navigation graph

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? enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 NavHosts. 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)
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...