Melakukan migrasi dari ViewPager ke ViewPager2

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:

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:

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(), bukan getCount(). Selain namanya, metode ini tidak berubah.
  • Ganti createFragment(), bukan getItem(), dalam class adaptor berbasis fragmen. Pastikan metode createFragment() 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:

  1. Ubah superclass ke RecyclerView.Adapter untuk penjelajahan halaman melalui tampilan, atau FragmentStateAdapter untuk penjelajahan halaman melalui fragmen.
  2. Ubah parameter konstruktor dalam class adaptor berbasis fragmen.
  3. Ganti getItemCount(), bukan getCount().
  4. Ganti createFragment() dan bukan getItem() 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

Video