ViewPager2
adalah versi library ViewPager
yang ditingkatkan, menawarkan fungsionalitas yang disempurnakan dan menangani kesulitan umum dalam penggunaan ViewPager
.
Jika aplikasi Anda sudah menggunakan ViewPager
, baca halaman ini untuk mempelajari lebih lanjut tentang migrasi ke ViewPager2
.
Jika ingin menggunakan ViewPager2
di aplikasi dan saat ini Anda tidak menggunakan ViewPager
, baca Bergeser di antara fragmen menggunakan ViewPager2 dan Membuat tampilan geser dengan tab menggunakan ViewPager2 untuk mengetahui informasi selengkapnya.
Manfaat migrasi ke ViewPager2
Alasan utama untuk melakukan migrasi adalah ViewPager2
akan menerima dukungan pengembangan aktif, sedangkan ViewPager
tidak. Namun, ViewPager2
juga menawarkan beberapa keuntungan khusus lainnya.
Dukungan orientasi vertikal
Selain penjelajahan halaman horizontal biasa, ViewPager2
juga mendukung penjelajahan halaman vertikal. Anda dapat mendukung penjelajahan halaman vertikal untuk elemen ViewPager2
dengan menetapkan atribut android:orientation
miliknya:
<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). Penjelajahan halaman RTL diaktifkan secara otomatis jika sesuai menurut lokal, tetapi Anda juga dapat mendukung penjelajahan halaman RTL secara manual untuk elemen ViewPager2
dengan menetapkan atribut android:layoutDirection
miliknya:
<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 penjelajahan halaman melalui kumpulan fragmen yang dapat diubah, memanggil notifyDatasetChanged()
untuk memperbarui UI saat kumpulan yang mendasarinya berubah.
Artinya, aplikasi Anda dapat memodifikasi kumpulan fragmen secara dinamis pada waktu proses, dan ViewPager2
akan menampilkan kumpulan yang dimodifikasi dengan benar.
DiffUtil
ViewPager2
dikembangkan dari RecyclerView
, yang berarti library ini memiliki akses ke class utilitas DiffUtil
. Kemampuan ini memberikan beberapa manfaat, tetapi yang paling penting, ini berarti objek ViewPager2
akan secara native memanfaatkan animasi perubahan set data dari class RecyclerView
.
Memigrasikan aplikasi ke ViewPager2
Ikuti langkah-langkah berikut untuk memperbarui objek ViewPager
di aplikasi Anda ke ViewPager2
:
Perbarui 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" />
Perbarui class adaptor
Saat menggunakan ViewPager
, Anda harus memperluas class adaptor yang menyediakan halaman baru ke objek tersebut. Tergantung pada kasus penggunaannya, ViewPager
menggunakan tiga class abstrak yang berbeda. ViewPager2
hanya menggunakan dua class abstrak.
Untuk setiap objek ViewPager
yang Anda ubah menjadi objek ViewPager2
, perbarui class adaptor untuk memperluas class abstrak yang sesuai seperti berikut:
- Saat
ViewPager
menggunakanPagerAdapter
untuk menelusuri tampilan, gunakanRecyclerView.Adapter
denganViewPager2
. - Saat
ViewPager
menggunakanFragmentPagerAdapter
untuk menelusuri fragmen dalam jumlah kecil yang tetap, gunakanFragmentStateAdapter
denganViewPager2
. - Saat
ViewPager
menggunakanFragmentStatePagerAdapter
untuk menelusuri fragmen dalam jumlah besar atau jumlah yang tidak diketahui, gunakanFragmentStateAdapter
denganViewPager2
.
Parameter konstruktor
Class adaptor berbasis fragmen yang mendapatkan turunan dari FragmentPagerAdapter
atau FragmentStatePagerAdapter
selalu menerima objek FragmentManager
tunggal sebagai parameter konstruktor. Saat memperluas FragmentStateAdapter
untuk class adaptor ViewPager2
, Anda memiliki opsi berikut untuk parameter konstruktor:
- Objek
FragmentActivity
atau objekFragment
tempat objekViewPager2
berada. Pada umumnya, opsi ini akan lebih baik. - Objek
FragmentManager
dan objekLifecycle
.
Class adaptor berbasis tampilan yang mendapatkan turunan langsung dari RecyclerView.Adapter
tidak memerlukan parameter konstruktor.
Mengganti metode
Class adaptor juga perlu mengganti metode yang berbeda untuk ViewPager2
dibandingkan untuk ViewPager
:
- Ganti
getItemCount()
, bukangetCount()
. Selain namanya, metode ini tidak berubah. - Ganti
createFragment()
, bukangetItem()
, dalam class adaptor berbasis fragmen. Pastikan metodecreateFragment()
baru Anda selalu menyediakan instance fragmen baru setiap kali fungsi dipanggil, bukan menggunakan kembali instance.
Ringkasan
Singkatnya, untuk mengubah class adaptor ViewPager
agar dapat digunakan dengan ViewPager2
, Anda harus melakukan perubahan berikut:
- Ubah superclass ke
RecyclerView.Adapter
untuk penjelajahan halaman melalui tampilan, atauFragmentStateAdapter
untuk penjelajahan halaman melalui fragmen. - Ubah parameter konstruktor dalam class adaptor berbasis fragmen.
- Ganti
getItemCount()
, bukangetCount()
. - Ganti
createFragment()
dan bukangetItem()
dalam 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 memfaktorkan ulang objek TabLayout
untuk integrasi dengan ViewPager2
.
TabLayout
telah dipisahkan dari ViewPager2
dan sekarang tersedia sebagai bagian dari Komponen material. Artinya, untuk menggunakannya, Anda perlu menambahkan dependensi yang sesuai ke file build.gradle
:
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 langsung 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 memperbarui kode yang menambahkan objek TabLayout
ke objek ViewPager
. Meskipun TabLayout
menggunakan metode setupWithViewPager()
miliknya sendiri untuk integrasi dengan ViewPager
, instance TabLayoutMediator
akan diperlukan untuk integrasi dengan ViewPager2
.
Objek TabLayoutMediator
juga menangani tugas untuk menghasilkan judul halaman bagi objek TabLayout
yang berarti class adaptor tidak perlu menggantikan 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 memuatnya. Misalnya, scroll tidak akan berfungsi untuk tampilan scroll vertikal di dalam objek ViewPager2
berorientasi vertikal.
Untuk mendukung tampilan scroll dalam objek ViewPager2
dengan orientasi yang sama, Anda harus memanggil requestDisallowInterceptTouchEvent()
pada objek ViewPager2
jika ingin men-scroll elemen bertingkat. Contoh scroll bertingkat ViewPager2 menunjukkan satu cara untuk mengatasi masalah ini dengan tata letak wrapper kustom serbaguna.
Referensi lainnya
Untuk mempelajari ViewPager2
lebih lanjut, baca referensi tambahan berikut ini.
Contoh
- Contoh ViewPager2 di GitHub
Video
- Turning the Page: Migrating to ViewPager2 (Android Dev Summit '19)