ViewPager2 هو إصدار محسَّن من مكتبة ViewPager توفّر
تم تحسين الوظائف ومعالجة الصعوبات الشائعة في استخدام ViewPager.
إذا كان تطبيقك يستخدم "ViewPager"، اقرأ هذه الصفحة لمعرفة مزيد من المعلومات عن
نقل البيانات إلى ViewPager2.
في حال أردت استخدام "ViewPager2" في تطبيقك وعدم استخدامه حاليًا
ViewPager، اقرأ التمرير بين الأجزاء باستخدام
ViewPager2 وإنشاء طرق عرض بالتمرير باستخدام
علامات تبويب تستخدم ViewPager2 لمزيد من
المعلومات.
مزايا نقل البيانات إلى ViewPager2
السبب الرئيسي لنقل البيانات هو أنّ ViewPager2 مفعَّل
لتطوير البرامج، بينما لا يكون الهدف ViewPager كذلك. مع ذلك، يقدّم ViewPager2 أيضًا
والعديد من المزايا المحددة الأخرى.
دعم الاتجاه العمودي
تتيح ميزة ViewPager2 الصفحات العمودية بالإضافة إلى الصفحات الأفقية التقليدية.
الترحيل. يمكنك تفعيل النقل العمودي لعنصر ViewPager2 من خلال ضبط إعداداته
السمة android:orientation:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:orientation="vertical" />
يمكنك أيضًا ضبط هذه السمة آليًا باستخدام setOrientation() .
دعم من اليمين إلى اليسار
تتيح ميزة "ViewPager2" التنقل من اليمين إلى اليسار (RTL). تم تفعيل الانتقال من لغة إلى آخر من خلال "المراسلة النصية في الوقت الفعلي".
تلقائيًا حيثما كان ذلك مناسبًا بناءً على اللغة، ولكن يمكنك أيضًا
يتيح هذا الخيار الانتقال إلى عنوان URL من النوع "إلى اليمين" في عنصر ViewPager2 من خلال ضبط.
السمة android:layoutDirection:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layoutDirection="rtl" />
يمكنك أيضًا ضبط هذه السمة آليًا باستخدام setLayoutDirection() .
مجموعات الأجزاء القابلة للتعديل
توفّر الدالة ViewPager2 التنقل خلال مجموعة أجزاء قابلة للتعديل،
يتصل
notifyDatasetChanged()
لتعديل واجهة المستخدم عند تغيُّر المجموعة الأساسية.
وهذا يعني أن تطبيقك يمكنه تعديل مجموعة الأجزاء ديناميكيًا على
وقت التشغيل، وسيعرض ViewPager2 المجموعة المعدّلة بشكل صحيح.
التردد
تم إنشاء ViewPager2 على RecyclerView،
مما يعني أنه يمكنها الوصول إلى
أداة DiffUtil
الصف. ينتج عن ذلك العديد من الفوائد، لكن أبرزها يعني
تستفيد كائنات ViewPager2 في الأصل من الرسوم المتحركة لتغيير مجموعة البيانات
من الفئة RecyclerView.
نقل تطبيقك إلى ViewPager2
اتّبِع الخطوات التالية لتعديل ViewPager عنصرًا في تطبيقك إلى الإصدار ViewPager2:
تعديل ملفات تنسيق XML
أولاً، استبدِل عناصر ViewPager في ملفات تنسيق XML باستخدام
عناصر 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" />
تعديل صفوف المحوّلات
عند استخدام الدالة ViewPager، كان عليك تمديد فئة المحوّل التي
الذي قدّم صفحات جديدة إلى الكائن. استنادًا إلى حالة الاستخدام، تم استخدام ViewPager.
لثلاث فصول نظرية مختلفة. لا يستخدم ViewPager2 سوى صفَين موجزَين فقط.
عليك تحويل كل عنصر ViewPager إلى عنصر ViewPager2.
عدِّل فئة المحوّل لتوسيع الفئة المجرّدة المناسبة على النحو التالي:
- عندما تم استخدام
PagerAdapterلتصفّح الصفحات في المشاهدات من قِبل "ViewPager"، استخدِمRecyclerView.AdapterمعViewPager2. - عندما استخدم
ViewPagerFragmentPagerAdapterلتصفح مجموعة صغيرة، عدد ثابت من الأجزاء، استخدمFragmentStateAdapterمعViewPager2. - عند استخدام "
ViewPager" للسمةFragmentStatePagerAdapterفي الصفحات خلال عدد كبير أو غير معروف من الأجزاء، استخدِمFragmentStateAdapterمعViewPager2
المَعلمات المنشئة
فئات المهايئات المستندة إلى الأجزاء المكتسبة من FragmentPagerAdapter أو
تقبل FragmentStatePagerAdapter دائمًا كائن FragmentManager واحد.
كمعلمة الدالة الإنشائية. عند تمديد فترة FragmentStateAdapter لمدة
فئة المحوّل ViewPager2، تتوفَّر لك الخيارات التالية للدالة الإنشائية.
المعلمات بدلاً من ذلك:
- الكائن
FragmentActivityأو الكائنFragmentحيث يوجد كائنViewPager2. وفي معظم الحالات، يكون هذا هو الخيار الأفضل. - كائن
FragmentManagerوكائنLifecycle.
فئات المهايئات المستندة إلى الملف الشخصي التي يتم نسخها مباشرةً من RecyclerView.Adapter إلى إجراء
لا تتطلب معلمة الدالة الإنشائية.
طرق الإلغاء
يجب أيضًا أن تلغي فئات المحوّلات الطرق المختلفة في ViewPager2.
مقارنةً بنسبة ViewPager:
- بدلاً من
getCount()، يمكنك إلغاءgetItemCount(). بخلاف الاسم، لم يتم تغيير هذه الطريقة. - بدلاً من
getItem()، يمكنك إلغاءcreateFragment()في شكل تقسيم. وفئات المهايئات. احرص على استخدام طريقةcreateFragment()الجديدة دائمًا توفر مثيلاً جديدًا للجزء في كل مرة يتم استدعاء الدالة بدلاً من حالات إعادة استخدام.
ملخّص
باختصار، لتحويل فئة محوّل ViewPager لاستخدامها مع ViewPager2،
يجب إجراء التغييرات التالية:
- تغيير الفئة الفائقة إلى
RecyclerView.Adapterللتنقل بين المشاهداتFragmentStateAdapterللتنقل بين الأجزاء. - تغيير معلمات الدالة الإنشائية في فئات المهايئات المستندة إلى الأجزاء.
- يمكنك إلغاء
getItemCount()بدلاً منgetCount(). - إلغاء
createFragment()بدلاً منgetItem()في المحوّل المستند إلى التجزئة الصفوف.
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
طرح ViewPager2 تغييرات على عملية دمج TabLayout إذا كنت
تستخدِم حاليًا عنصر ViewPager مع كائن TabLayout للعرض أفقيًا
للتنقل، يجب إعادة ضبط الكائن TabLayout من أجل
التكامل مع ViewPager2.
تم فصل TabLayout عن ViewPager2 وهو متاح الآن كجزء من
مكوّنات Material: وهذا يعني أنه من أجل استخدامها، تحتاج إلى إضافة
التبعية المناسبة لملف build.gradle:
Groovy
implementation "com.google.android.material:material:1.1.0-beta01"
Kotlin
implementation("com.google.android.material:material:1.1.0-beta01")
ويتعين عليك أيضًا تغيير موقع العنصر TabLayout في التسلسل الهرمي
ملف تخطيط XML الخاص بك. من خلال ViewPager، يتم تعريف العنصر TabLayout على أنّه
تابعة للعنصر ViewPager؛ ولكن مع ViewPager2، العنصر TabLayout
أعلى العنصر ViewPager2 مباشرةً، على المستوى نفسه:
<!-- 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>
أخيرًا، يجب تعديل الرمز البرمجي الذي يُرفِق الكائن TabLayout
كائن ViewPager. في حين أنّ "TabLayout" يستخدم setupWithViewPager() الخاص به
لدمجها مع ViewPager، فإنها تتطلب TabLayoutMediator
لدمجها مع ViewPager2.
يعالج الكائن TabLayoutMediator أيضًا مهمة إنشاء عناوين الصفحات.
للكائن TabLayout، ما يعني أنّ فئة المحوّل لن تحتاج إلى
إلغاء 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(); } ... }
دعم العناصر المدمجة القابلة للتمرير
لا تتيح ViewPager2 في الأساس عروض التمرير المُدمَجة في الحالات التي
طريقة عرض التمرير لها نفس اتجاه الكائن ViewPager2 الذي يحتوي على
بها. على سبيل المثال، لا يعمل التمرير لعرض التمرير العمودي داخل
كائن ViewPager2 باتجاه عمودي.
لتوفير إمكانية عرض التنقّل داخل عنصر ViewPager2 بالاتجاه نفسه،
يجب الاتصال
requestDisallowInterceptTouchEvent() في الكائن ViewPager2 عند
نتوقع تمرير العنصر المضمن بدلاً من ذلك. تمرير ViewPager2 المدمج
النموذج إلى طريقة واحدة لحل هذه المسألة باستخدام أساليب متعددة
تنسيق برنامج تضمين مخصّص.
مصادر إضافية
لمزيد من المعلومات حول ViewPager2، يُرجى الاطّلاع على المراجع الإضافية التالية.
نماذج
- نماذج ViewPager2 على GitHub
الفيديوهات
- تحويل الصفحة: النقل إلى ViewPager2 (مؤتمر Android Dev Summit 2019)