ViewPager2
adalah versi library ViewPager
yang telah ditingkatkan, yang menawarkan
fungsi yang ditingkatkan dan mengatasi 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 Menggeser antar-fragmen menggunakan
ViewPager2 dan Membuat tampilan geser dengan
tab menggunakan ViewPager2 untuk informasi
selengkapnya.
Manfaat migrasi ke ViewPager2
Alasan utama untuk melakukan migrasi adalah ViewPager2
menerima dukungan
pengembangan aktif, sedangkan ViewPager
tidak. Namun, ViewPager2
juga menawarkan
beberapa keuntungan 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,
yang memanggil
notifyDatasetChanged()
untuk mengupdate UI saat koleksi yang mendasarinya berubah.
Artinya, aplikasi Anda dapat secara dinamis memodifikasi kumpulan fragmen saat
runtime, dan ViewPager2
akan menampilkan koleksi yang dimodifikasi dengan benar.
DiffUtil
ViewPager2
dibuat di RecyclerView
,
yang berarti memiliki akses ke
class utilitas
DiffUtil
. Hal ini menghasilkan beberapa manfaat, tetapi yang terutama berarti bahwa
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 tersebut. 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
,
update 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 dan tetap, gunakanFragmentStateAdapter
denganViewPager2
. - Saat
ViewPager
menggunakanFragmentStatePagerAdapter
untuk menelusuri fragmen dalam jumlah besar atau tidak diketahui, gunakanFragmentStateAdapter
denganViewPager2
.
Parameter konstruktor
Class adaptor berbasis fragmen yang mewarisi 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
FragmentActivity
atau objekFragment
tempat objekViewPager2
berada. Pada umumnya, opsi ini akan lebih baik. - Objek
FragmentManager
dan objekLifecycle
.
Class adaptor berbasis tampilan yang mewarisi 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 mengonversi class adaptor ViewPager
agar dapat digunakan dengan ViewPager2
,
Anda harus melakukan perubahan berikut:
- Ubah superclass menjadi
RecyclerView.Adapter
untuk paging melalui tampilan, atauFragmentStateAdapter
untuk paging 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, agar dapat 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 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 melampirkan objek TabLayout
ke
objek ViewPager
. Meskipun menggunakan metode setupWithViewPager()
sendiri untuk berintegrasi dengan ViewPager
, TabLayout
memerlukan instance TabLayoutMediator
untuk berintegrasi dengan ViewPager2
.
Objek TabLayoutMediator
juga menangani tugas membuat 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
memuatnya. Misalnya, scroll tidak akan berfungsi untuk tampilan scroll vertikal di dalam
objek ViewPager2
berorientasi vertikal.
Untuk mendukung tampilan scroll di dalam objek ViewPager2
dengan orientasi yang sama,
Anda harus memanggil
requestDisallowInterceptTouchEvent()
pada objek ViewPager2
jika Anda
mengharapkan untuk men-scroll elemen bertingkat. Contoh scroll bertingkat ViewPager2 menunjukkan salah 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)