ViewPager2 est une version améliorée de la bibliothèque ViewPager qui offre des fonctionnalités améliorées et résout les problèmes courants liés à l'utilisation de ViewPager.
Si votre application utilise déjà ViewPager, poursuivez votre lecture pour en savoir plus au sujet de la migration vers ViewPager2.
Si vous souhaitez utiliser ViewPager2 dans votre application et que vous n'utilisez pas actuellement ViewPager, consultez Glisser entre des fragments à l'aide de ViewPager2 et Créer des vues à balayer avec des onglets à l'aide de ViewPager2 pour plus d'informations.
Avantages de la migration vers ViewPager2
La principale raison de migrer est que ViewPager2 bénéficie d'une assistance au développement active, contrairement à ViewPager. Toutefois, ViewPager2 offre également plusieurs autres avantages spécifiques.
Prise en charge de l'orientation verticale
ViewPager2 est compatible avec la pagination verticale en plus de la pagination horizontale traditionnelle. Vous pouvez activer la pagination verticale pour un élément ViewPager2 en définissant son attribut android:orientation :
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:orientation="vertical" />
Vous pouvez également définir cet attribut de manière programmatique à l'aide de la méthode setOrientation().
Compatibilité avec la mise en page de droite à gauche
ViewPager2 est compatible avec la pagination de droite à gauche. La pagination de droite à gauche est activée automatiquement, le cas échéant, en fonction des paramètres régionaux. Toutefois, vous pouvez également l'activer manuellement pour un élément ViewPager2 en définissant son attribut android:layoutDirection :
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layoutDirection="rtl" />
Vous pouvez également définir cet attribut de manière programmatique à l'aide de la méthode setLayoutDirection().
Collections de fragments modifiables
ViewPager2 permet de paginer une collection modifiable de fragments, en appelant notifyDatasetChanged() pour mettre à jour l'UI lorsque la collection sous-jacente change.
Cela signifie que votre application peut modifier de manière dynamique la collection de fragments au moment de l'exécution, et que ViewPager2 affichera correctement la collection modifiée.
DiffUtil
ViewPager2 est basé sur RecyclerView, ce qui signifie qu'il a accès à la classe utilitaire DiffUtil. Cela présente plusieurs avantages, mais surtout, cela signifie que les objets ViewPager2 profitent de manière native des animations de modification de l'ensemble de données de la classe RecyclerView.
Migrer votre application vers ViewPager2
Pour remplacer les objets ViewPager par ViewPager2 dans votre application, procédez comme suit :
Mettre à jour les fichiers de mise en page XML
Tout d'abord, remplacez les éléments ViewPager de vos fichiers de mise en page XML par des éléments ViewPager2 :
<!-- A ViewPager element -->
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- A ViewPager2 element -->
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Mettre à jour les classes d'adaptateur
Lorsque vous utilisiez ViewPager, vous deviez étendre la classe d'adaptateur qui fournissait de nouvelles pages à l'objet. Selon le cas d'utilisation, ViewPager a utilisé trois classes abstraites différentes. ViewPager2 n'utilise que deux classes abstraites.
Pour chaque objet ViewPager que vous convertissez en objet ViewPager2, mettez à jour la classe d'adaptateur pour étendre la classe abstraite appropriée comme suit :
- Lorsque
ViewPagerutilisaitPagerAdapterpour parcourir les vues, utilisezRecyclerView.AdapteravecViewPager2. - Lorsque
ViewPagerutilisaitFragmentPagerAdapterpour parcourir un petit nombre fixe de fragments, utilisezFragmentStateAdapteravecViewPager2. - Lorsque
ViewPagerutilisaitFragmentStatePagerAdapterpour paginer un nombre important ou inconnu de fragments, utilisezFragmentStateAdapteravecViewPager2.
Paramètres du constructeur
Les classes d'adaptateur basées sur des fragments qui héritent de FragmentPagerAdapter ou FragmentStatePagerAdapter acceptent toujours un seul objet FragmentManager comme paramètre de constructeur. Lorsque vous étendez FragmentStateAdapter pour une classe d'adaptateur ViewPager2, vous disposez des options suivantes pour les paramètres de constructeur :
- Objet
FragmentActivityouFragmentdans lequel réside l'objetViewPager2. Dans la plupart des cas, il s'agit de la meilleure option. - Un objet
FragmentManageret un objetLifecycle.
Les classes d'adaptateur basées sur des vues qui héritent directement de RecyclerView.Adapter ne nécessitent pas de paramètre de constructeur.
Ignorer les méthodes
Vos classes d'adaptateur doivent également remplacer différentes méthodes pour ViewPager2 par rapport à ViewPager :
- Au lieu de
getCount(), remplacezgetItemCount(). À part le nom, cette méthode reste inchangée. - Au lieu de
getItem(), remplacezcreateFragment()dans les classes d'adaptateur basées sur des fragments. Assurez-vous que votre nouvelle méthodecreateFragment()fournit toujours une nouvelle instance de fragment chaque fois que la fonction est appelée, au lieu de réutiliser des instances.
Résumé
En résumé, pour convertir une classe d'adaptateur ViewPager afin de l'utiliser avec ViewPager2, vous devez apporter les modifications suivantes :
- Remplacez la super-classe par
RecyclerView.Adapterpour paginer les vues ou parFragmentStateAdapterpour paginer les fragments. - Modifiez les paramètres du constructeur dans les classes d'adaptateur basées sur des fragments.
- Remplacez
getItemCount()au lieu degetCount(). - Remplacement de
createFragment()au lieu degetItem()dans les classes d'adaptateur basées sur des fragments.
Kotlin
// A simple ViewPager adapter class for paging through fragments class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { override fun getCount(): Int = NUM_PAGES override fun getItem(position: Int): Fragment = ScreenSlidePageFragment() } // An equivalent ViewPager2 adapter class class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) { override fun getItemCount(): Int = NUM_PAGES override fun createFragment(position: Int): Fragment = ScreenSlidePageFragment() }
Java
// A simple ViewPager adapter class for paging through fragments public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlidePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return new ScreenSlidePageFragment(); } @Override public int getCount() { return NUM_PAGES; } } // An equivalent ViewPager2 adapter class private class ScreenSlidePagerAdapter extends FragmentStateAdapter { public ScreenSlidePagerAdapter(FragmentActivity fa) { super(fa); } @Override public Fragment createFragment(int position) { return new ScreenSlidePageFragment(); } @Override public int getItemCount() { return NUM_PAGES; } }
Refactoriser les interfaces TabLayout
ViewPager2 introduit des modifications dans l'intégration de TabLayout. Si vous utilisez actuellement un ViewPager avec un objet TabLayout pour afficher des onglets horizontaux pour la navigation, vous devez refactoriser l'objet TabLayout pour l'intégrer à ViewPager2.
TabLayout a été dissocié de ViewPager2 et est désormais disponible dans les composants Material. Cela signifie que pour l'utiliser, vous devez ajouter la dépendance appropriée à votre fichier build.gradle :
Groovy
implementation "com.google.android.material:material:1.1.0-beta01"
Kotlin
implementation("com.google.android.material:material:1.1.0-beta01")
Vous devez également modifier l'emplacement de l'élément TabLayout dans la hiérarchie de votre fichier de mise en page XML. Avec ViewPager, l'élément TabLayout est déclaré en tant qu'enfant de l'élément ViewPager. En revanche, avec ViewPager2, l'élément TabLayout est déclaré directement au-dessus de l'élément ViewPager2, au même niveau :
<!-- A ViewPager element with a TabLayout -->
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.viewpager.widget.ViewPager>
<!-- A ViewPager2 element with a TabLayout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Enfin, vous devez mettre à jour le code qui associe l'objet TabLayout à l'objet ViewPager. Bien que TabLayout utilise sa propre méthode setupWithViewPager() pour s'intégrer à ViewPager, il nécessite une instance TabLayoutMediator pour s'intégrer à ViewPager2.
L'objet TabLayoutMediator gère également la tâche de génération des titres de la page pour l'objet TabLayout, ce qui signifie que la classe d'adaptateur n'a pas besoin de remplacer getPageTitle() :
Kotlin
// Integrating TabLayout with ViewPager class CollectionDemoFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tabLayout = view.findViewById(R.id.tab_layout) tabLayout.setupWithViewPager(viewPager) } ... } class DemoCollectionPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { override fun getCount(): Int = 4 override fun getPageTitle(position: Int): CharSequence { return "OBJECT ${(position + 1)}" } ... } // Integrating TabLayout with ViewPager2 class CollectionDemoFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tabLayout = view.findViewById(R.id.tab_layout) TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = "OBJECT ${(position + 1)}" }.attach() } ... }
Java
// Integrating TabLayout with ViewPager public class CollectionDemoFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { TabLayout tabLayout = view.findViewById(R.id.tab_layout); tabLayout.setupWithViewPager(viewPager); } ... } public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { ... @Override public int getCount() { return 4; } @Override public CharSequence getPageTitle(int position) { return "OBJECT " + (position + 1); } ... } // Integrating TabLayout with ViewPager2 public class CollectionDemoFragment : Fragment() { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { TabLayout tabLayout = view.findViewById(R.id.tab_layout); new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText("OBJECT " + (position + 1)) ).attach(); } ... }
Prendre en charge les éléments déroulants imbriqués
ViewPager2 n'est pas compatible de manière native avec les vues à défilement imbriquées lorsque la vue à défilement a la même orientation que l'objet ViewPager2 qui la contient. Par exemple, le défilement ne fonctionnerait pas pour une vue à défilement vertical dans un objet ViewPager2 orienté verticalement.
Pour prendre en charge une vue avec défilement dans un objet ViewPager2 ayant la même orientation, vous devez appeler requestDisallowInterceptTouchEvent() sur l'objet ViewPager2 lorsque vous souhaitez faire défiler l'élément imbriqué. L'exemple de défilement imbriqué ViewPager2 montre comment résoudre ce problème à l'aide d'une mise en page de wrapper personnalisée polyvalente.
Ressources supplémentaires
Pour en savoir plus sur ViewPager2, consultez les ressources supplémentaires suivantes.
Vidéos
- Tourner la page : Migrer vers ViewPager2 (Sommet des développeurs Android 2019)