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 แล้ว
โดยอัตโนมัติตามความเหมาะสม โดยอิงตามภาษา แต่คุณสามารถ
เปิดใช้การแบ่งหน้า 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
รองรับการแบ่งหน้าผ่านคอลเล็กชัน Fragment ที่แก้ไขได้
การโทร
notifyDatasetChanged()
เพื่ออัปเดต UI เมื่อคอลเล็กชันที่สำคัญมีการเปลี่ยนแปลง
ซึ่งหมายความว่าแอปสามารถแก้ไขคอลเล็กชัน Fragment แบบไดนามิกได้ที่
และ 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
ใช้ไปแล้ว ทั้งนี้ขึ้นอยู่กับกรณีการใช้งาน
คลาสนามธรรมที่แตกต่างกัน 3 คลาส ViewPager2
ใช้คลาสนามธรรมเพียง 2 คลาส
สำหรับออบเจ็กต์ ViewPager
แต่ละรายการที่คุณกำลังแปลงเป็นออบเจ็กต์ ViewPager2
อัปเดตคลาสอะแดปเตอร์เพื่อขยายคลาส Abstract ที่เหมาะสมดังนี้
- เมื่อ
ViewPager
ใช้PagerAdapter
เพื่อเลื่อนดูหน้าเว็บ ให้ใช้RecyclerView.Adapter
กับViewPager2
- เมื่อ
ViewPager
ใช้FragmentPagerAdapter
เพื่อเลื่อนดู จำนวนคงที่ของส่วนย่อย ให้ใช้FragmentStateAdapter
กับViewPager2
- เมื่อ
ViewPager
ใช้FragmentStatePagerAdapter
เพื่อแบ่งหน้า ส่วนย่อยจำนวนมากหรือไม่ทราบจำนวน ให้ใช้FragmentStateAdapter
กับViewPager2
พารามิเตอร์ตัวสร้าง
คลาสอะแดปเตอร์ที่อิงตาม Fragment ที่รับช่วงมาจาก FragmentPagerAdapter
หรือ
FragmentStatePagerAdapter
ยอมรับออบเจ็กต์ FragmentManager
รายการเดียวเ��มอ
เป็นพารามิเตอร์ตัวสร้าง เมื่อคุณขยายเวลา FragmentStateAdapter
เป็นเวลา
ประเภทอะแดปเตอร์ ViewPager2
คุณมีตัวเลือกต่อไปนี้สำหรับตัวสร้าง
แทน:
- ออบเจ็กต์
FragmentActivity
หรือออบเจ็กต์Fragment
ที่ มีออบเจ็กต์ViewPager2
รายการ ในกรณีส่วนใหญ่ ตัวเลือกนี้เหมาะสมกว่า - ออบเจ็กต์
FragmentManager
และออบเจ็กต์Lifecycle
คลาสอะแดปเตอร์ที่อิงตามการดูที่รับช่วงมาจาก RecyclerView.Adapter
โดยตรง
ไม่จำเป็นต้องใช้พารามิเตอร์ตัวสร้าง
วิธีการลบล้าง
คลาสอะแดปเตอร์ยังต้องลบล้างเมธอดต่างๆ สำหรับ ViewPager2
ด้วย
เมื่อเทียบกับ ViewPager
- ลบล้าง
getItemCount()
แทนgetCount()
นอกเหนือจากชื่อ วิธีการนี้จะไม่มีการเปลี่ยนแปลง - แทนที่
getItem()
ให้ลบล้างcreateFragment()
ในส่วนย่อย คลาสอะแดปเตอร์ใหม่ ตรวจสอบว่าใช้เมธอดcreateFragment()
ใหม่เสมอ จะใส่อินสแตนซ์ส่วนย่อยใหม่ทุกครั้งที่มีการเรียกฟังก์ชัน การนำอินสแตนซ์มาใช้ซ้ำ
สรุป
กล่าวโดยสรุปคือ หากต้องการแปลงคลาสอะแดปเตอร์ ViewPager
เพื่อใช้กับ ViewPager2
คุณต้องทำการเปลี่ยนแปลงต่อไปนี้
- ���ปลี่ยน Superclass เป็น
RecyclerView.Adapter
สำหรับการแบ่งหน้ายอดดู หรือFragmentStateAdapter
สำหรับการแบ่งหน้าส่วนย่อย - เปลี่ยนพารามิเตอร์ตัวสร้างในคลาสอะแดปเตอร์ที่อิงตาม Fragment
- ลบล้าง
getItemCount()
แทนgetCount()
- ลบล้าง
createFragment()
แทนgetItem()
ในอะแดปเตอร์ที่อิงตาม Fragment ใหม่
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
แล้ว และขณะนี้พร้อมให้บริการโดยเป็นส่วนหนึ่งของ
ส่วนประกอบของวัสดุ ซึ่งหมายความว่าคุณจะต้องเพิ่ม
ทรัพยากร Dependency ที่เหมาะสมสำหรับไฟล์ 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 Dev Summit ปี 2019)