ViewPager2
ist eine verbesserte Version der ViewPager
-Bibliothek mit
erweiterte Funktionalität und behandelt häufige Probleme bei der Verwendung von ViewPager
.
Wenn deine App bereits ViewPager
verwendet, findest du auf dieser Seite weitere Informationen zu
wird zu ViewPager2
migriert.
Wenn Sie ViewPager2
in Ihrer App verwenden möchten und derzeit nicht
ViewPager
, lesen Sie den Abschnitt Zwischen Fragmenten wechseln mit
ViewPager2 und Wischansichten erstellen mit
mit ViewPager2.
Informationen.
Vorteile der Migration zu ViewPager2
Der Hauptgrund für die Migration ist, dass ViewPager2
aktiv ist
Entwicklungssupport, ViewPager
jedoch nicht. ViewPager2
bietet aber auch
einige weitere spezifische Vorteile.
Unterstützung der vertikalen Ausrichtung
ViewPager2
unterstützt neben herkömmlichem horizontalem Paging auch vertikales Paging
Paging. Sie können vertikales Paging für ein ViewPager2
-Element aktivieren, indem Sie seine
Attribut android:orientation
:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:orientation="vertical" />
Sie können dieses Attribut auch programmatisch festlegen mithilfe der setOrientation() .
Rechts-nach-links-Unterstützung
ViewPager2
unterstützt das Seiten rechts nach links (rechts-nach-links, RTL). RTL-Paginierung ist aktiviert
automatisch je nach Sprache. Sie können aber auch
Aktivieren Sie RTL-Paginierung für ein ViewPager2
-Element, indem Sie seine
Attribut android:layoutDirection
:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layoutDirection="rtl" />
Sie können dieses Attribut auch programmatisch festlegen mithilfe der setLayoutDirection() .
Bearbeitbare Fragmentsammlungen
ViewPager2
unterstützt das Durchblättern einer änderbaren Sammlung von Fragmenten.
Anrufen
notifyDatasetChanged()
um die UI zu aktualisieren, wenn sich die zugrunde liegende Sammlung ändert.
Das bedeutet, dass Ihre Anwendung die Fragmentsammlung dynamisch ändern kann,
Laufzeit und ViewPager2
zeigt die geänderte Sammlung korrekt an.
DiffUtil
ViewPager2
basiert auf RecyclerView
,
Das bedeutet, sie hat Zugriff auf die
DiffUtil
-Dienstprogramm
. Daraus ergeben sich mehrere Vorteile, vor allem aber bedeutet es, dass
ViewPager2
-Objekte nutzen die Änderungsanimationen des Datasets nativ
aus der Klasse RecyclerView
.
Anwendung zu ViewPager2 migrieren
So aktualisieren Sie ViewPager
-Objekte in Ihrer App auf ViewPager2
:
XML-Layoutdateien aktualisieren
Ersetzen Sie zuerst die ViewPager
-Elemente in Ihren XML-Layoutdateien durch
ViewPager2
-Elemente:
<!-- 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" />
Adapterklassen aktualisieren
Bei der Verwendung von ViewPager
mussten Sie die Adapterklasse erweitern,
hat dem -Objekt neue Seiten bereitgestellt. Je nach Anwendungsfall wurde ViewPager
verwendet
drei verschiedenen abstrakten Klassen. ViewPager2
verwendet nur zwei abstrakte Klassen.
Für jedes ViewPager
-Objekt, das Sie in ein ViewPager2
-Objekt konvertieren,
Aktualisieren Sie die Adapterklasse, um die entsprechende abstrakte Klasse wie folgt zu erweitern:
- Wenn
ViewPager
PagerAdapter
verwendet hat, um durch Ansichten zu blättern, verwenden SieRecyclerView.Adapter
mitViewPager2
. - Wenn
ViewPager
mitFragmentPagerAdapter
durch eine kleine, feste Anzahl von Fragmenten verwenden, verwenden SieFragmentStateAdapter
mitViewPager2
. - Wenn
ViewPager
FragmentStatePagerAdapter
verwendet hat, um durch ein große oder unbekannte Anzahl von Fragmenten, verwenden SieFragmentStateAdapter
mitViewPager2
Konstruktorparameter
Fragmentbasierte Adapterklassen, die von FragmentPagerAdapter
übernehmen oder
FragmentStatePagerAdapter
akzeptiert immer ein einzelnes FragmentManager
-Objekt.
als Konstruktorparameter. Wenn Sie FragmentStateAdapter
um eine
ViewPager2
haben, stehen Ihnen für den Konstruktor folgende Optionen zur Verfügung:
Parameter:
- Das
FragmentActivity
- oderFragment
-Objekt, an dem derViewPager2
-Objekt befindet. In den meisten Fällen ist dies die bessere Option. - Ein
FragmentManager
-Objekt und einLifecycle
-Objekt.
Ansichtsbasierte Adapterklassen, die direkt von RecyclerView.Adapter
übernehmen, tun dies
benötigen keinen Konstruktorparameter.
Überschreibungsmethoden
Ihre Adapterklassen müssen auch verschiedene Methoden für ViewPager2
überschreiben
als beim ViewPager
:
- Überschreiben Sie
getItemCount()
anstelle vongetCount()
. Abgesehen vom Namen bleibt die Methode unverändert. - Anstelle von
getItem()
createFragment()
im fragmentierten Modus überschreiben Adapterklassen zu erstellen. Achten Sie darauf, dass die neuecreateFragment()
-Methode immer stellt bei jedem Aufruf der Funktion eine neue Fragmentinstanz bereit, wiederverwendbaren Instanzen.
Zusammenfassung
Zusammenfassend lässt sich sagen, dass zum Konvertieren einer ViewPager
-Adapterklasse für die Verwendung mit ViewPager2
Folgendes gilt:
müssen Sie folgende Änderungen vornehmen:
- Ändern Sie die Basisklasse in
RecyclerView.Adapter
, um durch die Ansichten zu blättern, oderFragmentStateAdapter
zum Durchblättern von Fragmenten - Ändern Sie die Konstruktorparameter in fragmentierten Adapterklassen.
getItemCount()
anstelle vongetCount()
überschreiben.createFragment()
anstelle vongetItem()
im fragmentierten Adapter überschreiben Klassen.
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; } }
TabLayout-Oberflächen refaktorieren
Mit ViewPager2
werden Änderungen an der TabLayout
-Integration eingeführt. Wenn Sie
Derzeit wird zur horizontalen Darstellung ein ViewPager
mit einem TabLayout
-Objekt verwendet.
Tabs für die Navigation verwenden möchten, müssen Sie das TabLayout
-Objekt für
Integration mit ViewPager2
.
TabLayout
wurde von ViewPager2
entkoppelt und ist jetzt im Rahmen von
Material-Komponenten. Wenn Sie sie verwenden möchten, müssen Sie
entsprechende Abhängigkeit zu Ihrer build.gradle
-Datei:
Cool
implementation "com.google.android.material:material:1.1.0-beta01"
Kotlin
implementation("com.google.android.material:material:1.1.0-beta01")
Außerdem müssen Sie die Position des TabLayout
-Elements in der Hierarchie von
in Ihrer XML-Layoutdatei ein. Mit ViewPager
wird das TabLayout
-Element als
dem ViewPager
-Element untergeordnet ist. aber mit ViewPager2
ist das TabLayout
-Element
direkt über dem Element ViewPager2
auf derselben Ebene deklariert:
<!-- 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>
Abschließend müssen Sie den Code aktualisieren, durch den das TabLayout
-Objekt an die
ViewPager
-Objekt. Während TabLayout
eine eigene setupWithViewPager()
verwendet
zur Integration von ViewPager
verwenden, ist ein TabLayoutMediator
erforderlich.
Instanz für die Integration in ViewPager2
.
Das TabLayoutMediator
-Objekt übernimmt auch das Generieren von Seitentiteln
für das TabLayout
-Objekt. Das bedeutet, dass die Adapterklasse
getPageTitle()
überschreiben:
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(); } ... }
Verschachtelte scrollbare Elemente unterstützen
ViewPager2
unterstützt verschachtelte Scroll-Ansichten nicht nativ, wenn der
hat die gleiche Ausrichtung wie das ViewPager2
-Objekt, das
. Beispielsweise funktioniert das Scrollen bei einer vertikalen Scroll-Ansicht innerhalb eines
vertikal ausgerichtetes ViewPager2
-Objekt.
So unterstützen Sie eine Scroll-Ansicht innerhalb eines ViewPager2
-Objekts mit derselben Ausrichtung:
du musst anrufen
requestDisallowInterceptTouchEvent()
für das ViewPager2
-Objekt, wenn Sie
wird stattdessen das verschachtelte Element gescrollt. Das verschachtelte Scrollen mit ViewPager2
Beispiel zeigt eine Möglichkeit zur Lösung dieses Problems mit einem vielseitigen
Benutzerdefiniertes Wrapper-Layout.
Weitere Informationen
Weitere Informationen zu ViewPager2
finden Sie in den folgenden zusätzlichen Ressourcen.
Produktproben
- ViewPager2-Beispiele auf GitHub
Videos
- Turning the Page: Migrating to ViewPager2 (Android Dev Summit '19)