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
, consultez cette page pour en savoir plus sur la migration vers ViewPager2
.
Si vous souhaitez utiliser ViewPager2
dans votre application et que vous n'utilisez pas actuellement ViewPager
, consultez Faire glisser des fragments à l'aide de ViewPager2 et Créer des vues à balayer avec des onglets à l'aide de ViewPager2 pour en savoir plus.
Avantages de la migration vers ViewPager2
La principale raison de la migration est que ViewPager2
bénéficie d'une assistance de développement active, contrairement à ViewPager
. Cependant, 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 par programmation à l'aide de la méthode setOrientation().
Soutien de droite à gauche
ViewPager2
est compatible avec la pagination de droite à gauche. La pagination de droite à gauche est activée automatiquement en fonction des paramètres régionaux, mais 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 par programmation à l'aide de la méthode setLayoutDirection().
Collections de fragments modifiables
ViewPager2
permet la pagination via une collection de fragments modifiable, en appelant notifyDatasetChanged()
pour mettre à jour l'interface utilisateur 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
affiche 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 cela signifie notamment que les objets ViewPager2
exploitent de manière native les animations de modification de l'ensemble de données de la classe RecyclerView
.
Migrer votre application vers ViewPager2
Pour mettre à jour les objets ViewPager
de votre application vers ViewPager2
, procédez comme suit:
Mettre à jour des fichiers de mise en page XML
Tout d'abord, remplacez les éléments ViewPager
dans 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 avez dû étendre la classe d'adaptateur qui fournissait les 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 de l'adaptateur pour étendre la classe abstraite appropriée, comme suit:
- Lorsque
ViewPager
utilisaitPagerAdapter
pour parcourir les vues, utilisezRecyclerView.Adapter
avecViewPager2
. - Lorsque
ViewPager
utilisaitFragmentPagerAdapter
pour parcourir un petit nombre fixe de fragments, utilisezFragmentStateAdapter
avecViewPager2
. - Lorsque
ViewPager
utiliseFragmentStatePagerAdapter
pour parcourir un nombre important ou inconnu de fragments, utilisezFragmentStateAdapter
avecViewPager2
.
Paramètres du constructeur
Les classes d'adaptateurs basées sur des fragments qui héritent de FragmentPagerAdapter
ou FragmentStatePagerAdapter
acceptent toujours un seul objet FragmentManager
en tant que paramètre constructeur. Lorsque vous étendez FragmentStateAdapter
pour une classe d'adaptateur ViewPager2
, vous disposez des options suivantes pour les paramètres de constructeur:
- Objet
FragmentActivity
ou objetFragment
où se trouve l'objetViewPager2
. Dans la plupart des cas, il s'agit de la meilleure option. - Un objet
FragmentManager
et un objetLifecycle
Les classes d'adaptateurs basées sur les vues qui héritent directement de RecyclerView.Adapter
ne nécessitent pas de paramètre constructeur.
Ignorer les méthodes
Vos classes d'adaptateur doivent également remplacer des méthodes pour ViewPager2
et ViewPager
:
- Au lieu de
getCount()
, remplacezgetItemCount()
. Hormis le nom, cette méthode reste inchangée. - Au lieu de
getItem()
, remplacezcreateFragment()
dans les classes d'adaptateurs 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
à utiliser avec ViewPager2
, vous devez apporter les modifications suivantes:
- Remplacez la super-classe par
RecyclerView.Adapter
pour la pagination via les vues ou parFragmentStateAdapter
pour la pagination via des fragments. - Modifiez les paramètres du constructeur dans les classes d'adaptateur basées sur des fragments.
- Ignorez
getItemCount()
au lieu degetCount()
. - Remplacement de
createFragment()
au lieu degetItem()
dans les classes d'adaptateurs 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
apporte des modifications à 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é comme enfant de l'élément ViewPager
. 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 de titres de 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éfilement imbriqués
ViewPager2
n'est pas compatible de manière native avec les vues de défilement imbriquées lorsque celle-ci a la même orientation que l'objet ViewPager2
qui la contient. Par exemple, le défilement ne fonctionne pas pour une vue à défilement vertical dans un objet ViewPager2
orienté verticalement.
Pour accepter une vue de défilement dans un objet ViewPager2
avec la même orientation, vous devez appeler requestDisallowInterceptTouchEvent()
sur l'objet ViewPager2
si vous prévoyez de faire défiler l'élément imbriqué à la place. L'exemple de défilement imbriqué ViewPager2 illustre une façon de résoudre ce problème avec une mise en page de wrapper personnalisée polyvalente.
Ressources supplémentaires
Pour en savoir plus sur ViewPager2
, consultez les ressources supplémentaires suivantes.
Exemples
- Exemples de ViewPager2 sur GitHub
Vidéos
- Tourner la page : Migrer vers ViewPager2 (Sommet des développeurs Android 2019)