ViewPager'den ViewPager2'ye geçiş

ViewPager2, ViewPager kitaplığının gelişmiş işlevler sunan ve ViewPager kullanımıyla ilgili yaygın sorunları gideren iyileştirilmiş bir sürümüdür. Uygulamanızda zaten ViewPager kullanılıyorsa ViewPager2 hizmetine taşıma hakkında daha fazla bilgi edinmek için bu sayfayı okuyun.

Uygulamanızda ViewPager2 kullanıyor ve şu anda ViewPager kullanmıyorsanız daha fazla bilgi için ViewPager2 kullanarak parçalar arasında kaydırma ve ViewPager2 kullanarak sekmelerle kaydırma görünümleri oluşturma başlıklı makaleleri okuyun.

ViewPager2'ye geçmenin avantajları

Geçişin birincil nedeni, ViewPager2 adresinin aktif geliştirme desteği alması ve ViewPager alan adının almamasıdır. Bununla birlikte, ViewPager2 başka özel avantajlar da sunar.

Dikey yön desteği

ViewPager2, geleneksel yatay sayfalamanın yanı sıra dikey sayfalamayı da destekler. Bir ViewPager2 öğesinin android:orientation özelliğini ayarlayarak bu öğe için dikey sayfa oluşturmayı etkinleştirebilirsiniz:

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />

Bu özelliği, setOrientation() yöntemini kullanarak programatik olarak da ayarlayabilirsiniz.

Sağdan sola desteği

ViewPager2, sağdan sola (RTL) sayfalamayı destekler. sağdan sola sayfalama, uygun olduğunda yerel ayara göre otomatik olarak etkinleştirilir. Ancak bir ViewPager2 öğesinin android:layoutDirection özelliğini ayarlayarak RTL sayfalandırmayı manuel olarak da etkinleştirebilirsiniz:

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layoutDirection="rtl" />

Bu özelliği, setLayoutDirection() yöntemini kullanarak programatik olarak da ayarlayabilirsiniz.

Değiştirilebilir parça koleksiyonları

ViewPager2, değiştirilebilir bir parça koleksiyonunda sayfalandırmayı destekler ve temel koleksiyon değiştiğinde kullanıcı arayüzünü güncellemek için notifyDatasetChanged() çağrısı yapar.

Bu, uygulamanızın çalışma zamanında parça koleksiyonunu dinamik olarak değiştirebileceği ve ViewPager2 ürününün değiştirilen koleksiyonu doğru şekilde görüntüleyebileceği anlamına gelir.

DifUtil

ViewPager2, RecyclerView üzerinde derlendiği için DiffUtil yardımcı program sınıfına erişebilir. Bu, çeşitli avantajlar sağlar, ancak en önemlisi ViewPager2 nesnelerinin yerel olarak RecyclerView sınıfındaki veri kümesi değişiklik animasyonlarından yararlanması anlamına gelir.

Uygulamanızı ViewPager2'ye taşıyın

Uygulamanızdaki ViewPager nesneyi ViewPager2 olarak güncellemek için şu adımları uygulayın:

XML düzen dosyalarını güncelleme

İlk olarak, XML düzen dosyalarınızdaki ViewPager öğelerini ViewPager2 öğeleriyle değiştirin:

<!-- 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" />

Bağdaştırıcı sınıflarını güncelleme

ViewPager kullanırken, nesneye yeni sayfalar sağlayan bağdaştırıcı sınıfını genişletmeniz gerekiyordu. Kullanım alanına bağlı olarak, ViewPager üç farklı soyut sınıf kullandı. ViewPager2 yalnızca iki soyut sınıf kullanır.

ViewPager2 nesnesine dönüştürdüğünüz her ViewPager nesnesi için bağdaştırıcı sınıfını uygun soyut sınıfı aşağıdaki gibi genişletecek şekilde güncelleyin:

Oluşturucu parametreleri

FragmentPagerAdapter veya FragmentStatePagerAdapter öğesinden devralan parçaya dayalı bağdaştırıcı sınıfları, kurucu parametresi olarak her zaman tek bir FragmentManager nesnesini kabul eder. FragmentStateAdapter öğesini bir ViewPager2 bağdaştırıcı sınıfı için genişlettiğinizde kurucu parametreleri için aşağıdaki seçenekleriniz olur:

  • ViewPager2 nesnesinin bulunduğu FragmentActivity veya Fragment nesnesi. Çoğu durumda bu daha iyi bir seçenektir.
  • Bir FragmentManager nesnesi ve bir Lifecycle nesnesi.

Doğrudan RecyclerView.Adapter öğesinden devralan görüntüleme tabanlı bağdaştırıcı sınıfları, kurucu parametresi gerektirmez.

Geçersiz kılma yöntemleri

Bağdaştırıcı sınıflarınızın, ViewPager için olduğundan ViewPager2 için farklı yöntemleri de geçersiz kılması gerekir:

  • getCount() yerine getItemCount() değerini geçersiz kılın. Bu yöntemde ad dışında herhangi bir değişiklik yapılmamıştır.
  • getItem() yerine, parça tabanlı adaptör sınıflarında createFragment() değerini geçersiz kılın. İşlev her çağrıldığında, örnekleri yeniden kullanmak yerine yeni createFragment() yönteminizin her zaman yeni bir parça örneği sağladığından emin olun.

Özet

Özet olarak, ViewPager2 ile kullanmak üzere bir ViewPager bağdaştırıcı sınıfını dönüştürmek için aşağıdaki değişiklikleri yapmanız gerekir:

  1. Görünümler arasında sayfalama yapmak için üst sınıfı RecyclerView.Adapter veya parçalar arasında sayfalama yapmak için FragmentStateAdapter olarak değiştirin.
  2. Parça tabanlı bağdaştırıcı sınıflarındaki oluşturucu parametrelerini değiştirin.
  3. getCount() yerine getItemCount() değerini geçersiz kılın.
  4. Parça tabanlı bağdaştırıcı sınıflarında getItem() yerine createFragment() değerini geçersiz kılın.

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;
    }
}

TabLayout arayüzlerini yeniden düzenleme

ViewPager2, TabLayout entegrasyonuyla ilgili değişiklikler sunuyor. Şu anda gezinme için yatay sekmeleri görüntülemek amacıyla TabLayout nesnesine sahip bir ViewPager kullanıyorsanız TabLayout nesnesini ViewPager2 ile entegrasyon için yeniden düzenlemeniz gerekir.

TabLayout, ViewPager2 öğesinden ayrıldı ve artık Malzeme bileşenleri'nin bir parçası olarak kullanılabilir. Yani, kullanabilmek için build.gradle dosyanıza uygun bağımlılığı eklemeniz gerekir:

Modern

implementation "com.google.android.material:material:1.1.0-beta01"

Kotlin

implementation("com.google.android.material:material:1.1.0-beta01")

Ayrıca, TabLayout öğesinin XML düzen dosyanızın hiyerarşisindeki konumunu da değiştirmeniz gerekir. ViewPager kullanıldığında TabLayout öğesi, ViewPager öğesinin alt öğesi olarak tanımlanır; ancak ViewPager2 ile TabLayout öğesi, doğrudan ViewPager2 öğesinin üzerinde, aynı düzeyde tanımlanır:

<!-- 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>

Son olarak, TabLayout nesnesini ViewPager nesnesine ekleyen kodu güncellemeniz gerekir. TabLayout, ViewPager ile entegrasyon için kendi setupWithViewPager() yöntemini kullanır ancak ViewPager2 ile entegrasyon için TabLayoutMediator örneği gerekir.

TabLayoutMediator nesnesi, TabLayout nesnesi için sayfa başlıkları oluşturma görevini de yerine getirir. Bu, bağdaştırıcı sınıfının getPageTitle() öğesini geçersiz kılmasına gerek olmadığı anlamına gelir:

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();
    }
    ...
}

İç içe kaydırılabilir öğeleri destekleme

ViewPager2, kaydırma görünümünün kendisini içeren ViewPager2 nesnesiyle aynı yöne sahip olduğu durumlarda iç içe yerleştirilmiş kaydırma görünümlerini yerel olarak desteklemez. Örneğin, dikey yönlü bir ViewPager2 nesnesinin içindeki dikey kaydırma görünümünde kaydırma işlemi çalışmaz.

Aynı yöne sahip bir ViewPager2 nesnesinin içinde kaydırma görünümünü desteklemek için iç içe yerleştirilmiş öğeyi kaydırmayı beklediğinizde ViewPager2 nesnesinde requestDisallowInterceptTouchEvent() işlevini çağırmanız gerekir. ViewPager2 iç içe yerleştirilmiş kaydırma örneği, bu sorunu çok yönlü bir özel sarmalayıcı düzeni ile çözmenin bir yolunu göstermektedir.

Ek kaynaklar

ViewPager2 hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara bakın.

Sana Özel

Videolar