ViewPager2 adalah versi yang ditingkatkan dari library ViewPager yang menawarkan
fungsi yang ditingkatkan dan menangani kesulitan umum dalam penggunaan ViewPager.
Jika aplikasi Anda sudah menggunakan ViewPager, baca halaman ini untuk mempelajari lebih lanjut cara
bermigrasi ke ViewPager2.
Jika Anda ingin menggunakan ViewPager2 di aplikasi dan saat ini tidak menggunakan
ViewPager, baca Bergeser antar-fragmen menggunakan
ViewPager2 dan Membuat tampilan geser dengan
tab menggunakan ViewPager2 untuk informasi
selengkapnya.
Manfaat migrasi ke ViewPager2
Alasan utama untuk bermigrasi adalah karena ViewPager2 menerima dukungan pengembangan aktif, sedangkan ViewPager tidak. Namun, ViewPager2 juga menawarkan
beberapa keunggulan spesifik lainnya.
Dukungan orientasi vertikal
ViewPager2 mendukung paging vertikal selain paging horizontal
tradisional. Anda dapat mengaktifkan paging vertikal untuk elemen ViewPager2 dengan menetapkan
atribut android:orientation-nya:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:orientation="vertical" />
Anda juga dapat menetapkan atribut ini secara terprogram menggunakan metode setOrientation().
Dukungan kanan-ke-kiri
ViewPager2 mendukung penjelajahan halaman kanan-ke-kiri (RTL). Paging RTL diaktifkan
secara otomatis jika sesuai berdasarkan lokalitas, tetapi Anda juga dapat mengaktifkan
paging RTL secara manual untuk elemen ViewPager2 dengan menetapkan
atribut android:layoutDirection-nya:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layoutDirection="rtl" />
Anda juga dapat menetapkan atribut ini secara terprogram menggunakan metode setLayoutDirection().
Kumpulan fragmen yang dapat diubah
ViewPager2 mendukung paging melalui kumpulan fragmen yang dapat diubah,
memanggil
notifyDatasetChanged()
untuk mengupdate UI saat kumpulan yang mendasarinya berubah.
Artinya, aplikasi Anda dapat mengubah koleksi fragmen secara dinamis saat
runtime, dan ViewPager2 akan menampilkan koleksi yang diubah dengan benar.
DiffUtil
ViewPager2 dibuat di RecyclerView,
yang berarti memiliki akses ke class utilitas
DiffUtil. Hal ini memberikan beberapa manfaat, tetapi yang paling penting adalah
objek ViewPager2 secara native memanfaatkan animasi perubahan set data
dari class RecyclerView.
Memigrasikan aplikasi Anda ke ViewPager2
Ikuti langkah-langkah berikut untuk memperbarui objek ViewPager di aplikasi Anda ke ViewPager2:
Memperbarui file tata letak XML
Pertama, ganti elemen ViewPager dalam file tata letak XML Anda dengan
elemen 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" />
Memperbarui class adaptor
Saat menggunakan ViewPager, Anda harus memperluas class adaptor yang
menyediakan halaman baru ke objek. Bergantung pada kasus penggunaan, ViewPager menggunakan
tiga class abstrak yang berbeda. ViewPager2 hanya menggunakan dua class abstrak.
Untuk setiap objek ViewPager yang Anda konversi menjadi objek ViewPager2,
perbarui class adaptor untuk memperluas class abstrak yang sesuai sebagai berikut:
- Jika
ViewPagermenggunakanPagerAdapteruntuk menelusuri tampilan, gunakanRecyclerView.AdapterdenganViewPager2. - Jika
ViewPagermenggunakanFragmentPagerAdapteruntuk menelusuri sejumlah kecil fragmen tetap, gunakanFragmentStateAdapterdenganViewPager2. - Saat
ViewPagermenggunakanFragmentStatePagerAdapteruntuk melakukan paging pada fragmen dalam jumlah besar atau tidak diketahui, gunakanFragmentStateAdapterdenganViewPager2.
Parameter konstruktor
Class adaptor berbasis fragmen yang diwarisi dari FragmentPagerAdapter atau
FragmentStatePagerAdapter selalu menerima satu objek FragmentManager
sebagai parameter konstruktor. Saat memperluas FragmentStateAdapter untuk
class adaptor ViewPager2, Anda memiliki opsi berikut untuk parameter
konstruktor:
- Objek
FragmentActivityatau objekFragmenttempat objekViewPager2berada. Pada umumnya, opsi ini akan lebih baik. - Objek
FragmentManagerdan objekLifecycle.
Class adaptor berbasis tampilan yang diwarisi langsung dari RecyclerView.Adapter tidak
memerlukan parameter konstruktor.
Mengganti metode
Class adaptor Anda juga perlu mengganti metode yang berbeda untuk ViewPager2
daripada yang dilakukan untuk ViewPager:
- Ganti
getItemCount(), bukangetCount(). Selain nama, metode ini tidak berubah. - Sebagai ganti
getItem(), ganticreateFragment()di class adaptor berbasis fragmen. Pastikan metodecreateFragment()baru Anda selalu menyediakan instance fragmen baru setiap kali fungsi dipanggil, bukan menggunakan kembali instance.
Ringkasan
Singkatnya, untuk mengonversi class adaptor ViewPager agar dapat digunakan dengan ViewPager2,
Anda harus melakukan perubahan berikut:
- Ubah superclass menjadi
RecyclerView.Adapteruntuk paging melalui tampilan, atauFragmentStateAdapteruntuk paging melalui fragmen. - Ubah parameter konstruktor dalam class adaptor berbasis fragmen.
- Ganti
getItemCount(), bukangetCount(). - Ganti
createFragment(), bukangetItem()di class adaptor berbasis fragmen.
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; } }
Faktorkan ulang antarmuka TabLayout
ViewPager2 memperkenalkan perubahan pada integrasi TabLayout. Jika saat ini Anda menggunakan ViewPager dengan objek TabLayout untuk menampilkan tab horizontal untuk navigasi, Anda perlu merefaktorisasi objek TabLayout untuk integrasi dengan ViewPager2.
TabLayout telah dipisahkan dari ViewPager2 dan kini tersedia sebagai bagian dari
Komponen material. Artinya, untuk menggunakannya, Anda perlu menambahkan
dependensi yang sesuai ke file build.gradle:
Groovy
implementation "com.google.android.material:material:1.1.0-beta01"
Kotlin
implementation("com.google.android.material:material:1.1.0-beta01")
Anda juga perlu mengubah lokasi elemen TabLayout dalam hierarki
file tata letak XML. Dengan ViewPager, elemen TabLayout dideklarasikan sebagai
turunan dari elemen ViewPager; tetapi dengan ViewPager2, elemen TabLayout
dideklarasikan tepat di atas elemen ViewPager2, pada tingkat yang sama:
<!-- 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>
Terakhir, Anda harus mengupdate kode yang melampirkan objek TabLayout ke
objek ViewPager. Meskipun TabLayout menggunakan metode setupWithViewPager()
-nya sendiri untuk berintegrasi dengan ViewPager, memerlukan instance TabLayoutMediator
untuk berintegrasi dengan ViewPager2.
Objek TabLayoutMediator juga menangani tugas pembuatan judul halaman
untuk objek TabLayout, yang berarti class adaptor tidak perlu
mengganti 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(); } ... }
Dukung elemen bertingkat yang dapat di-scroll
ViewPager2 tidak mendukung tampilan scroll bertingkat secara native jika
tampilan scroll memiliki orientasi yang sama dengan objek ViewPager2 yang
berisi tampilan tersebut. Misalnya, scroll tidak akan berfungsi untuk tampilan scroll vertikal di dalam
objek ViewPager2 yang berorientasi vertikal.
Untuk mendukung tampilan scroll di dalam objek ViewPager2 dengan orientasi yang sama,
Anda harus memanggil
requestDisallowInterceptTouchEvent() pada objek ViewPager2 saat Anda
ingin men-scroll elemen bertingkat. Contoh scroll bertingkat ViewPager2 menunjukkan salah satu cara untuk menyelesaikan masalah ini dengan tata letak wrapper kustom yang serbaguna.
Referensi lainnya
Untuk mempelajari ViewPager2 lebih lanjut, baca referensi tambahan berikut ini.
Video
- Turning the Page: Migrating to ViewPager2 (Android Dev Summit '19)