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
. - عندما استخدم
ViewPager
FragmentPagerAdapter
لتصفح مجموعة صغيرة، عدد ثابت من الأجزاء، استخدم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)