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:
ViewPager
, sayfalar arasında geçiş yapmak içinPagerAdapter
değerini kullandığındaViewPager2
ileRecyclerView.Adapter
kullanın.ViewPager
, az ve sabit sayıda parçayı sayfalandırmak içinFragmentPagerAdapter
özelliğini kullandığındaViewPager2
ileFragmentStateAdapter
kullanın.ViewPager
, çok sayıda veya bilinmeyen sayıda parçayı sayfalamak içinFragmentStatePagerAdapter
kullanırkenViewPager2
ileFragmentStateAdapter
kullanın.
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ğuFragmentActivity
veyaFragment
nesnesi. Çoğu durumda bu daha iyi bir seçenektir.- Bir
FragmentManager
nesnesi ve birLifecycle
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()
yerinegetItemCount()
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ındacreateFragment()
değerini geçersiz kılın. İşlev her çağrıldığında, örnekleri yeniden kullanmak yerine yenicreateFragment()
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:
- Görünümler arasında sayfalama yapmak için üst sınıfı
RecyclerView.Adapter
veya parçalar arasında sayfalama yapmak içinFragmentStateAdapter
olarak değiştirin. - Parça tabanlı bağdaştırıcı sınıflarındaki oluşturucu 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()
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
- GitHub'da ViewPager2 örnekleri
Videolar
- Sayfayı Açma: ViewPager2 'ye Geçiş (Android Dev Summit 2019)