ViewPager2
是 ViewPager
程式庫的改良版本,該版本提供了
強化功能,並解決使用 ViewPager
的常見問題。
如果您的應用程式已使用 ViewPager
,請參閱本頁進一步瞭解
正在遷移至 ViewPager2
。
如果您想在應用程式中使用 ViewPager2
,但目前並未使用
ViewPager
,請參閱使用
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
元素的 RTL 分頁,以啟用 RTL 分頁
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()
在基礎集合變更時更新 UI。
也就是說,您的應用程式可以動態修改位於
然後 ViewPager2
正確顯示修改後的集合。
迪夫普斯
ViewPager2
以 RecyclerView
為建構基礎。
表示該 SDK 可存取
DiffUtil
公用程式
類別這麼做會帶來幾項好處
ViewPager2
物件原生使用資料集變更動畫
來自 RecyclerView
類別。
將應用程式遷移至 ViewPager2
請按照下列步驟將應用程式中的 ViewPager
物件更新為 ViewPager2
:
更新 XML 版面配置檔案
首先,將 XML 版面配置檔案中的 ViewPager
元素替換成
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
只會使用兩個抽象類別。
針對每個要轉換為 ViewPager2
物件的 ViewPager
物件
請更新轉接程式類別以擴充適當的抽象類別,如下所示:
- 如果
ViewPager
使用PagerAdapter
瀏覽檢視畫面,請使用RecyclerView.Adapter
(使用ViewPager2
)。 - 當
ViewPager
使用FragmentPagerAdapter
瀏覽一個小型檔案時 固定數量的片段,請搭配ViewPager2
使用FragmentStateAdapter
。 - 當
ViewPager
使用FragmentStatePagerAdapter
瀏覽 片段數量龐大或不明,請使用FragmentStateAdapter
搭配ViewPager2
。
建構函式參數
繼承自 FragmentPagerAdapter
或
FragmentStatePagerAdapter
一律接受單一 FragmentManager
物件
做為建構函式參數如果為 FragmentStateAdapter
擴充
ViewPager2
轉接器類別,您可以使用下列建構函式選項
參數:
FragmentActivity
物件或Fragment
物件,其中含有ViewPager2
物件也位於該物件中。在大多數的情況下,這是比較適合使用的選項。FragmentManager
物件和Lifecycle
物件。
直接從 RecyclerView.Adapter
繼承的 View 式轉接程式類別會執行以下動作:
不需要建構函式參數。
覆寫方法
您的轉接程式類別也需要覆寫 ViewPager2
的不同方法
相較於「ViewPager
」的行為:
- 請覆寫
getItemCount()
,而不是getCount()
。除了名稱 則此方法未變更。 - 請覆寫以片段為基礎的
createFragment()
,而非getItem()
轉接程式類別。請確保新的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
整合項目的變更。如果發生以下情況:
目前使用具有 TabLayout
物件的 ViewPager
顯示水平
以便瀏覽,您需要重構 TabLayout
物件,才能進行瀏覽
與 ViewPager2
整合。
TabLayout
與 ViewPager2
分離,現已成為下列產品的一員:
Material Design 元件。也就是說
適用於 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
物件相同
基礎架構舉例來說,捲動功能不支援 Google 應用程式中的垂直捲動檢視畫面
垂直導向 ViewPager2
物件。
如要在 ViewPager2
物件中支援相同方向的捲動檢視畫面,
你必須呼叫。
ViewPager2
物件上的 requestDisallowInterceptTouchEvent()
(當您執行以下動作時)
會預期改為捲動巢狀元素ViewPager2 巢狀捲動
範例示範使用多功能資源來解決這個問題的一種方法
自訂包裝函式版面配置。
其他資源
如要進一步瞭解 ViewPager2
,請參閱下列其他資源:
範例
- GitHub 上的 ViewPager2 範例
影片
- 翻頁:遷移至 MigratePager2 (2019 年 Android 開發人員高峰會)