نقل البيانات من ViewPager إلى ViewPager2

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. عدِّل فئة المحوّل لتوسيع الفئة المجرّدة المناسبة على النحو التالي:

المَعلمات المنشئة

فئات المهايئات المستندة إلى الأجزاء المكتسبة من FragmentPagerAdapter أو تقبل FragmentStatePagerAdapter دائمًا كائن FragmentManager واحد. كمعلمة الدالة الإنشائية. عند تمديد فترة FragmentStateAdapter لمدة فئة المحوّل ViewPager2، تتوفَّر لك الخيارات التالية للدالة الإنشائية. المعلمات بدلاً من ذلك:

  • الكائن FragmentActivity أو الكائن Fragment حيث يوجد كائن ViewPager2. وفي معظم الحالات، يكون هذا هو الخيار الأفضل.
  • كائن FragmentManager وكائن Lifecycle.

فئات المهايئات المستندة إلى الملف الشخصي التي يتم نسخها مباشرةً من RecyclerView.Adapter إلى إجراء لا تتطلب معلمة الدالة الإنشائية.

طرق الإلغاء

يجب أيضًا أن تلغي فئات المحوّلات الطرق المختلفة في ViewPager2. مقارنةً بنسبة ViewPager:

  • بدلاً من getCount()، يمكنك إلغاء getItemCount(). بخلاف الاسم، لم يتم تغيير هذه الطريقة.
  • بدلاً من getItem()، يمكنك إلغاء createFragment() في شكل تقسيم. وفئات المهايئات. احرص على استخدام طريقة createFragment() الجديدة دائمًا توفر مثيلاً جديدًا للجزء في كل مرة يتم استدعاء الدالة بدلاً من حالات إعادة استخدام.

ملخّص

باختصار، لتحويل فئة محوّل ViewPager لاستخدامها مع ViewPager2، يجب إجراء التغييرات التالية:

  1. تغيير الفئة الفائقة إلى RecyclerView.Adapter للتنقل بين المشاهدات FragmentStateAdapter للتنقل بين الأجزاء.
  2. تغيير معلمات الدالة الإنشائية في فئات المهايئات المستندة إلى الأجزاء.
  3. يمكنك إلغاء getItemCount() بدلاً من getCount().
  4. إلغاء 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، يُرجى الاطّلاع على المراجع الإضافية التالية.

نماذج

الفيديوهات