ViewPager2, ViewPager kitaplığının gelişmiş bir sürümüdür. Bu sürüm, gelişmiş işlevler sunar ve ViewPager kullanımıyla ilgili yaygın sorunları giderir.
Uygulamanızda ViewPager kullanılıyorsa ViewPager2 hizmetine geçiş hakkında daha fazla bilgi edinmek için bu sayfayı okuyun.
Uygulamanızda ViewPager2 kullanmak istiyorsanız 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ş yapmanın temel nedeni, ViewPager2 için etkin geliştirme desteği sunulurken ViewPager için sunulmamasıdır. Ancak ViewPager2, başka avantajlar da sunar.
Dikey yön desteği
ViewPager2, geleneksel yatay sayfalama özelliğinin yanı sıra dikey sayfalama özelliğini de destekler. android:orientation özelliğini ayarlayarak bir ViewPager2 öğesi için dikey sayfa gezginini 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) sayfa düzenini destekler. Sağdan sola sayfa gezgini, yerel ayara göre uygun olan yerlerde otomatik olarak etkinleştirilir ancak android:layoutDirection özelliğini ayarlayarak ViewPager2 öğesi için sağdan sola sayfa gezginini 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 sayfa gezginini destekler ve temel koleksiyon değiştiğinde kullanıcı arayüzünü güncellemek için notifyDatasetChanged() yöntemini çağırır.
Bu, uygulamanızın çalışma zamanında parça koleksiyonunu dinamik olarak değiştirebileceği ve ViewPager2 öğesinin değiştirilen koleksiyonu doğru şekilde göstereceği anlamına gelir.
DiffUtil
ViewPager2, RecyclerView üzerine kuruludur. Bu nedenle DiffUtil yardımcı program sınıfına erişebilir. Bu durum çeşitli avantajlar sağlar. En önemlisi, ViewPager2 nesnelerinin RecyclerView sınıfındaki veri kümesi değişikliği animasyonlarından doğal olarak yararlanmasıdır.
Uygulamanızı ViewPager2'ye taşıma
Uygulamanızdaki ViewPager nesnelerini ViewPager2 olarak güncellemek için aşağıdaki adımları uygulayın:
XML düzen dosyalarını güncelleme
Öncelikle 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 adaptör sınıfını, uygun soyut sınıfı aşağıdaki gibi genişletecek şekilde güncelleyin:
- Görünümler arasında gezinmek için
ViewPager,PagerAdapterkullandığındaViewPager2ileRecyclerView.Adapterkullanın. ViewPager, az sayıda sabit parçadan oluşan sayfalar arasında gezinmek içinFragmentPagerAdapterkullandığındaViewPager2ileFragmentStateAdapterkullanın.ViewPager, çok sayıda veya bilinmeyen sayıda parçayı sayfalara ayırmak içinFragmentStatePagerAdapterkullandığındaViewPager2ileFragmentStateAdapterkullanın.
Oluşturucu parametreleri
FragmentPagerAdapter veya FragmentStatePagerAdapter sınıfından devralınan parça tabanlı bağdaştırıcı sınıfları, her zaman kurucu parametresi olarak tek bir FragmentManager nesnesi kabul eder. ViewPager2 bağdaştırıcı sınıfı için FragmentStateAdapter sınıfını genişlettiğinizde, yapıcı parametreleri için aşağıdaki seçenekleri kullanabilirsiniz:
ViewPager2nesnesinin bulunduğuFragmentActivitynesnesi veyaFragmentnesnesi. Çoğu durumda bu daha iyi bir seçenektir.- Bir
FragmentManagernesnesi ve birLifecyclenesnesi.
Doğrudan RecyclerView.Adapter sınıfından devralınan görünüme dayalı bağdaştırıcı sınıfları için kurucu parametresi gerekmez.
Geçersiz kılma yöntemleri
Bağdaştırıcı sınıflarınızın, ViewPager2 için ViewPager'dekinden farklı yöntemleri geçersiz kılması da gerekir:
getCount()yerinegetItemCount()değerini geçersiz kılın. Adı dışında bu yöntemde herhangi bir değişiklik yapılmadı.getItem()yerine, parça tabanlı bağdaştırıcı sınıflarındacreateFragment()yöntemini geçersiz kılın. YenicreateFragment()yönteminizin, örnekleri yeniden kullanmak yerine işlev her çağrıldığında her zaman yeni bir parça örneği sağladığından emin olun.
Özet
Özetle, bir ViewPager bağdaştırıcı sınıfını ViewPager2 ile kullanılacak şekilde dönüştürmek için aşağıdaki değişiklikleri yapmanız gerekir:
- Görünümler arasında sayfa gezgini kullanmak için üst sınıfı
RecyclerView.Adapter, parçalar arasında sayfa gezgini kullanmak içinFragmentStateAdapterolarak değiştirin. - Parça tabanlı bağdaştırıcı sınıflarındaki kurucu parametrelerini değiştirin.
getCount()yerinegetItemCount()değerini geçersiz kılın.- Parça tabanlı bağdaştırıcı sınıflarında
getItem()yerinecreateFragment()yöntemini 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 entegrasyonunda değişiklikler yapıyor. Şu anda gezinme için yatay sekmeler görüntülemek üzere TabLayout nesnesiyle birlikte ViewPager kullanıyorsanız ViewPager2 ile entegrasyon için TabLayout nesnesini yeniden düzenlemeniz gerekir.
TabLayout, ViewPager2'den ayrıldı ve artık Materyal bileşenleri kapsamında kullanılabilir. Bu nedenle, kitaplığı kullanmak 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, XML düzen dosyanızın hiyerarşisinde TabLayout öğesinin konumunu da değiştirmeniz gerekir. ViewPager ile TabLayout öğesi, ViewPager öğesinin alt öğesi olarak tanımlanır. ViewPager2 ile ise 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ırken ViewPager2 ile entegrasyon için bir TabLayoutMediator örneği gerektirir.
TabLayoutMediator nesnesi, TabLayout nesnesi için sayfa başlıkları oluşturma görevini de üstlenir. Bu, adaptör sınıfının getPageTitle() yöntemini 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 yerleştirilmiş 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 olarak yönlendirilmiş 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çindeki kaydırma görünümünü desteklemek için iç içe yerleştirilmiş öğeyi kaydırmayı beklediğinizde ViewPager2 nesnesinde requestDisallowInterceptTouchEvent() yöntemini çağırmanız gerekir. ViewPager2 iç içe yerleştirilmiş kaydırma örneği, çok yönlü bir özel sarmalayıcı düzeni ile bu sorunu çözmenin bir yolunu gösterir.
Ek kaynaklar
ViewPager2 hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara göz atın.
Videolar
- Turning the Page: Migrating to ViewPager2 (Android Dev Summit '19)