Android Jetpack Navigation with ViewPager and TabLayout

对着背影说爱祢 提交于 2019-12-18 10:42:54

问题


For a new app i use Jetpack Navigation Library to implement proper back navigation. The first level of navigation is a navigation drawer which works fine with jetpack navigation as described in the documentation. But there is another level of navigation implemented with ViewPager and TabLayout. The fragments switched by the TabLayout contain additional linear navigation hierarchy. However, there seems to be no support for ViewPager/TabLayout in Jetpack Navigation. A FragmentPagerAdapter has to be implemented and the managed back stack ends when switching tabs. There is a disconnect between the top level navigation and the navigation inside each tab. Is there any way to make this work with Jetpack Navigation?


回答1:


Experimented with different approaches to handle TabLayout with Jetpack Navigation. But hit issues like having a full history of switching between tabs multiple times etc.

Browsing known Google Android Issues before raising a request for a demo, I found this existing issue.

Its status is Closed marked as Intended Behavior with the following explanation:

Navigation focuses on elements that affect the back stack and tabs do not affect the back stack - you should continue to manage tabs with a ViewPager and TabLayout - Referring to Youtube training.




回答2:


What worked for me so far:

In navigation_graph.xml

  • make your ViewPagerFragment the root of a nested graph
  • connect your in and out navigation to the nested graph

in nested graph:

  • add the ChildFragments of the ViewPager to the nested graph

I didnt need to change the ViewPager, and Directions were created for the Child Fragments so navigation is possible from there.




回答3:


Yes, but you will have to implement your own custom destination, by implementing the class Navigator and overriding at least the methods popBackStack() and navigate().

In your navigate, you will have to call the ViewPager.setCurrentTab() and add it to your back stack. Something like:

lateinit var viewPager: ViewPager? = null // you have to provide this in the constructor

private val backstack: Deque<Pair<Int, View>> = ArrayDeque

override fun navigate(destination: Destination, args: Bundle?,
                      navOptions: NavOptions?, navigatorExtras: Extras?
): NavDestination? {

    viewPager.currentItem = destination.id
    backstack.remove(destination.id) // remove so the stack has never two of the same
    backstack.addLast(destination.id)

    return destination
}

In your popBackStack, you will have to set back the last item selected. Something like:

override fun popBackStack(): Boolean {
    if(backstack.size() <= 1) return false

    viewPager.currentItem = backstack.peekLast()
    backstack.removeLast()

    return true
}

You can find a brief explanation on Android docs and this example of custom navigator for FragmentDialog.

After implementing your ViewPagerNavigator, you will have to add it to your NavController and set the listeners of tab views selection to call NavController.navigate().

I hope someone will implement a library for all this common patterns (ViewPager, ViewGroup, FragmentDialog), if anyone find it, put it on the comments.



来源:https://stackoverflow.com/questions/52540303/android-jetpack-navigation-with-viewpager-and-tablayout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!