Bermigrasi dari ViewPager ke ViewPager2

ViewPager2 adalah versi peningkatan library ViewPager yang menawarkan fungsi yang disempurnakan dan menangani kesulitan umum dalam menggunakan ViewPager. Jika aplikasi Anda sudah menggunakan ViewPager, baca halaman ini untuk mempelajari lebih lanjut yang dimigrasikan ke ViewPager2.

Jika Anda ingin menggunakan ViewPager2 di aplikasi dan saat ini tidak menggunakannya ViewPager, baca Bergeser antar-fragmen menggunakan ViewPager2 dan Membuat tampilan geser dengan tab yang menggunakan ViewPager2 untuk informasi lainnya tidak akurat atau tidak sesuai.

Manfaat migrasi ke ViewPager2

Alasan utama untuk melakukan migrasi adalah karena ViewPager2 menjadi aktif dukungan pengembangan dan ViewPager tidak. Namun, ViewPager2 juga menawarkan beberapa keuntungan spesifik lainnya.

Dukungan orientasi vertikal

ViewPager2 mendukung paging vertikal selain horizontal tradisional {i>paging<i}. Anda dapat mengaktifkan paging vertikal untuk elemen ViewPager2 dengan menyetel Atribut android:orientation:

<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 setOrientation() .

Dukungan kanan-ke-kiri

ViewPager2 mendukung penjelajahan halaman kanan-ke-kiri (RTL). Paging RTL diaktifkan secara otomatis jika perlu berdasarkan lokalitas, tetapi Anda juga dapat secara manual aktifkan paging RTL untuk elemen ViewPager2 dengan menyetel elemen Atribut android:layoutDirection:

<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 setLayoutDirection() .

Kumpulan fragmen yang dapat diubah

ViewPager2 mendukung paging melalui koleksi fragmen yang dapat dimodifikasi, menelepon notifyDatasetChanged() untuk mengupdate UI saat koleksi yang mendasarinya berubah.

Ini berarti bahwa aplikasi Anda dapat memodifikasi pengumpulan fragmen secara dinamis di runtime, dan ViewPager2 akan menampilkan koleksi yang diubah dengan benar.

DiffUtil

ViewPager2 dibuat di RecyclerView, artinya, ia memiliki akses ke Utilitas DiffUtil . Hal ini memberikan 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 halaman baru yang disediakan ke objek. Bergantung pada kasus penggunaannya, ViewPager digunakan 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 sebagai berikut:

Parameter konstruktor

Class adaptor berbasis fragmen yang mewarisi dari FragmentPagerAdapter atau FragmentStatePagerAdapter selalu menerima satu objek FragmentManager sebagai parameter konstruktor. Saat Anda memperluas FragmentStateAdapter untuk Class adaptor ViewPager2, Anda memiliki opsi berikut untuk konstruktor parameter sebagai gantinya:

Class adaptor berbasis tampilan yang mewarisi langsung dari RecyclerView.Adapter melakukan tidak memerlukan parameter konstruktor.

Mengganti metode

Class adaptor Anda juga perlu mengganti berbagai metode untuk ViewPager2 dibandingkan untuk ViewPager:

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

  1. Ubah superclass menjadi RecyclerView.Adapter untuk melakukan paging melalui tampilan, atau FragmentStateAdapter untuk melakukan paging melalui fragmen.
  2. Ubah parameter konstruktor dalam class adaptor berbasis fragmen.
  3. Ganti getItemCount(), bukan getCount().
  4. Mengganti createFragment(), bukan getItem() dalam adaptor berbasis fragmen Google Cloud Platform.

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 Anda saat ini menggunakan ViewPager dengan objek TabLayout untuk menampilkan 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. Ini berarti bahwa untuk menggunakannya, Anda perlu menambahkan dependensi yang sesuai untuk file build.gradle Anda:

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 Anda. 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 mengupdate kode yang melampirkan objek TabLayout ke Objek ViewPager. Meskipun TabLayout menggunakan setupWithViewPager()-nya sendiri untuk berintegrasi dengan ViewPager, diperlukan TabLayoutMediator untuk diintegrasikan dengan ViewPager2.

Objek TabLayoutMediator juga menangani tugas untuk membuat judul halaman untuk objek TabLayout, yang berarti bahwa class adaptor tidak perlu ganti 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 anotasi. Misalnya, men-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, kamu harus panggil requestDisallowInterceptTouchEvent() pada objek ViewPager2 saat Anda kita akan menggulir elemen tersarang. Scrolling bertingkat ViewPager2 contoh menunjukkan satu cara untuk menyelesaikan masalah ini dengan tata letak wrapper kustom.

Referensi lainnya

Untuk mempelajari ViewPager2 lebih lanjut, baca referensi tambahan berikut ini.

Contoh

Video