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). החלוקה לדפים בפורמט RTL מופעלת
באופן אוטומטי בהתאם למיקום, אך ניתן גם באופן ידני
להפעיל חלוקה לדפים מימין לרכיב 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 יציג בצורה נכונה את האוסף שהשתנה.
DiffUtil
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 יחיד
בתור פרמטר constructor. עם הארכה של FragmentStateAdapter למשך
סוג המתאם ViewPager2, יש את האפשרויות הבאות ל-constructor
במקום זאת:
- האובייקט
FragmentActivityאו האובייקטFragmentשבו נמצא אובייקטViewPager2. ברוב המקרים זו האפשרות הטובה ביותר. - אובייקט
FragmentManagerואובייקטLifecycle.
סוגי מתאמים מבוססי-תצוגה שעוברים בירושה ישירות מ-RecyclerView.Adapter
לא דורשים פרמטר של constructor.
שיטות לשינוי מברירת המחדל
סיווגי המתאם צריכים גם לשנות שיטות שונות עבור ViewPager2
מאשר במשך ViewPager:
- במקום
getCount(), משנים אתgetItemCount(). מלבד השם, השיטה הזו לא השתנתה. - במקום
getItem(), צריך לשנות אתcreateFragment()בגרסה שמבוססת על מקטעים של סוגי מתאמים. חשוב לוודא ששיטת הcreateFragment()החדשה תמיד פועלת מספקת מופע מקטע חדש בכל פעם קוראים לפונקציה במקום שימוש חוזר במכונות.
סיכום
לסיכום, כדי להמיר סיווג מתאם ViewPager לשימוש עם ViewPager2,
עליך לבצע את השינויים הבאים:
- לשנות את מחלקת העל ל-
RecyclerView.Adapterכדי לעבור בין תצוגות, אוFragmentStateAdapterכדי לעבור בין מקטעים. - שינוי הפרמטרים של ה-constructor בסוגי מתאמים שמבוססים על מקטעים.
- שינוי
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 והוא זמין עכשיו כחלק מ
רכיבי החומר. כלומר, כדי להשתמש בו צריך להוסיף
את התלות המתאימה בקובץ build.gradle שלכם:
מגניב
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
מדגים דרך אחת לפתרון הבעיה הזו באמצעות
פריסת wrapper מותאמת אישית.
מקורות מידע נוספים
מידע נוסף על ViewPager2 זמין במקורות המידע הנוספים הבאים.
דוגמיות
- דוגמאות ViewPager2 ב-GitHub
סרטונים
- הפיכת הדף: מעבר ל-ViewPager2 (כנס המפתחים של Android לשנת 2019)