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 appli utilise déjà ViewPager
, lisez cette page pour en savoir plus sur
migration vers ViewPager2
.
Si vous souhaitez utiliser ViewPager2
dans votre appli et que vous n'utilisez pas actuellement
ViewPager
, consultez Glisser entre des fragments en utilisant
ViewPager2 et Créer des vues à balayer avec
à l'aide de ViewPager2 pour en savoir plus
des informations.
Avantages de la migration vers ViewPager2
La principale raison de la migration est que ViewPager2
reçoit des
au développement, contrairement à ViewPager
. Cependant, ViewPager2
propose aussi
plusieurs autres avantages spécifiques.
Prise en charge de l'orientation verticale
ViewPager2
prend en charge la pagination verticale en plus de la pagination horizontale traditionnelle
la pagination. Vous pouvez activer la pagination verticale pour un élément ViewPager2
en définissant sa
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() .
Orientation de droite à gauche
ViewPager2
prend en charge la pagination de droite à gauche (RTL). Pagination de droite à gauche activée
automatiquement selon les paramètres régionaux, mais vous pouvez aussi
activer la pagination de droite à gauche 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
prend en charge la pagination via une collection modifiable de fragments,
Appel en cours
notifyDatasetChanged()
pour mettre à jour l'UI lorsque la collection sous-jacente change.
Cela signifie que votre application peut modifier dynamiquement la collection de fragments
et ViewPager2
affichera correctement la collection modifiée.
DiffUtil
ViewPager2
est basé sur RecyclerView
,
ce qui signifie qu'il a accès
Utilitaire DiffUtil
. Cela présente plusieurs avantages, mais cela signifie notamment
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
Procédez comme suit pour mettre à jour les objets ViewPager
de votre application vers ViewPager2
:
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
É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 utilisez ViewPager
, vous devez étendre la classe d'adaptateur que
a fourni de nouvelles pages à l'objet. Selon le cas d'utilisation, ViewPager
a utilisé
trois classes abstraites distinctes. 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
utilisePagerAdapter
pour parcourir les pages, utilisezRecyclerView.Adapter
avecViewPager2
- Lorsque
ViewPager
utilisaitFragmentPagerAdapter
pour parcourir une petite un nombre fixe de fragments, utilisezFragmentStateAdapter
avecViewPager2
. - Lorsque
ViewPager
a utiliséFragmentStatePagerAdapter
pour parcourir une nombre de fragments élevé ou inconnu, utilisezFragmentStateAdapter
avecViewPager2
Paramètres du constructeur
Les classes d'adaptateur basées sur des fragments qui héritent de FragmentPagerAdapter
ou
FragmentStatePagerAdapter
accepte toujours un seul objet FragmentManager
.
en tant que paramètre constructeur. Lorsque vous prolongez FragmentStateAdapter
pour
ViewPager2
, vous disposez des options suivantes pour le constructeur
paramètres à la place:
- L'objet
FragmentActivity
ouFragment
dans lequelViewPager2
est présent. Dans la plupart des cas, il s'agit de la meilleure option. - Un objet
FragmentManager
et un objetLifecycle
.
Les classes d'adaptateur basées sur les vues qui héritent directement de RecyclerView.Adapter
ont
ne nécessitent pas de paramètre constructeur.
Ignorer les méthodes
Vos classes d'adaptateur doivent aussi 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 requêtes basées sur des fragments les classes d'adaptateur. Assurez-vous que votre nouvelle méthodecreateFragment()
fournit une nouvelle instance de fragment chaque fois que la fonction est appelée au lieu de la réutilisation d'instances.
Résumé
En résumé, pour convertir une classe d'adaptateur ViewPager
à utiliser avec ViewPager2
,
vous devez apporter les modifications suivantes:
- Définissez la super-classe sur
RecyclerView.Adapter
pour la pagination des vues.FragmentStateAdapter
pour la pagination 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 l'adaptateur basé sur des fragments classes.
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
modifie l'intégration de TabLayout
. Si vous
utilisent actuellement un ViewPager
avec un objet TabLayout
pour un affichage horizontal
onglets pour la navigation, vous devez refactoriser l'objet TabLayout
pour
avec ViewPager2
.
TabLayout
a été dissocié de ViewPager2
et est désormais disponible dans le cadre de
Composants Material. Pour l'utiliser, vous devez donc 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 des
votre fichier de mise en page XML. Avec ViewPager
, l'élément TabLayout
est déclaré en tant que
enfant de l'élément ViewPager
; mais avec ViewPager2
, l'élément TabLayout
est déclarée 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
à la
ViewPager
. Bien que TabLayout
utilise sa propre classe setupWithViewPager()
pour intégrer ViewPager
, elle nécessite un TabLayoutMediator
à intégrer à ViewPager2
.
L'objet TabLayoutMediator
gère également la génération des titres de page.
pour l'objet TabLayout
, ce qui signifie que la classe d'adaptateur n'a pas besoin
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 à défilement imbriqué dans les cas où
la vue de défilement a la même orientation que l'objet ViewPager2
qui contient
Par exemple, le défilement ne fonctionne pas pour une vue de défilement vertical à l'intérieur d'une
objet ViewPager2
orienté verticalement.
Pour prendre en charge une vue de défilement dans un objet ViewPager2
ayant la même orientation :
vous devez appeler
requestDisallowInterceptTouchEvent()
sur l'objet ViewPager2
lorsque vous
s'attendent à faire défiler l'élément imbriqué à la place. Le défilement imbriqué ViewPager2
exemple illustre une façon de résoudre ce problème à l'aide d'une solution polyvalente
mise en page de wrapper personnalisée.
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)