web-dev-qa-db-fra.com

Android Navigation Jetpack avec ViewPager et TabLayout

Pour une nouvelle application, j'utilise la bibliothèque de navigation Jetpack pour implémenter une navigation arrière appropriée. Le premier niveau de navigation est un tiroir de navigation qui fonctionne très bien avec la navigation Jetpack comme décrit dans la documentation. Mais il existe un autre niveau de navigation implémenté avec ViewPager et TabLayout. Les fragments commutés par TabLayout contiennent une hiérarchie de navigation linéaire supplémentaire. Cependant, il ne semble pas y avoir de prise en charge de ViewPager/TabLayout dans la navigation Jetpack. Un FragmentPagerAdapter doit être implémenté et la pile arrière gérée se termine lors du changement d'onglets. Il existe un décalage entre la navigation de niveau supérieur et la navigation à l'intérieur de chaque onglet. Existe-t-il un moyen de faire fonctionner cela avec Jetpack Navigation?

19
ngu

Expérimenté avec différentes approches pour gérer TabLayout avec Navigation Jetpack . Mais rencontrez des problèmes comme avoir un historique complet de basculer entre les onglets plusieurs fois, etc.

Naviguer sur Google connu Android Problèmes avant de lancer une demande de démonstration, j'ai trouvé cela problème existant .

Son état est Fermé marqué comme Comportement prévu avec l'explication suivante:

La navigation se concentre sur les éléments qui affectent la pile arrière et les onglets n'affectent pas la pile arrière - vous devez continuer à gérer les onglets avec ViewPager et TabLayout - En vous référant à formation Youtube =.

7
sunadorer

Ce qui a fonctionné jusqu'à présent:

Dans navigation_graph.xml

  • faire de votre ViewPagerFragment la racine d'un graphique imbriqué
  • connectez votre navigation d'entrée et de sortie au graphique imbriqué

dans le graphe imbriqué:

  • ajouter les ChildFragments du ViewPager au graphique imbriqué

Je n'avais pas besoin de changer le ViewPager, et des directions ont été créées pour les fragments d'enfant afin que la navigation soit possible à partir de là.

1
user2965003

Oui , mais vous devrez implémenter votre propre destination personnalisée, en implémentant la classe Navigator et en remplaçant au moins les méthodes popBackStack() et navigate() .

Dans votre navigate, vous devrez appeler la ViewPager.setCurrentTab() et l'ajouter à votre back stack. Quelque chose comme:

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
}

Dans votre popBackStack, vous devrez reculer le dernier élément sélectionné. Quelque chose comme:

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

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

    return true
}

Vous pouvez trouver une brève explication sur documents Android et cet exemple du navigateur personnalisé pour FragmentDialog.

Après avoir implémenté votre ViewPagerNavigator, vous devrez l'ajouter à votre NavController et définir les écouteurs de la sélection des vues d'onglets pour appeler NavController.navigate().

J'espère que quelqu'un implémentera une bibliothèque pour tous ces modèles courants (ViewPager, ViewGroup, FragmentDialog), si quelqu'un le trouve, mettez-le dans les commentaires.

0
Allan Veloso