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() メソッドを呼び出します。
RTL(右から左)のサポート
ViewPager2 は、RTL(右から左)方向ページングをサポートしています。RTL ページングが有効
自動的に設定されますが、手動で
ViewPager2 要素の 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 は変更されたコレクションを正しく表示します。
DiffUtil
ViewPager2 は RecyclerView 上に構築されています。
アクセスできることを意味します
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 を使用するときは、Terraform でインフラストラクチャを
新しいページがオブジェクトに渡されました。ユースケースによっては、ViewPager を使用
3 種類の抽象クラスがあります。ViewPager2 の場合、使用する抽象クラスは 2 つだけで済みます。
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 から直接継承するビューベースのアダプタクラスは、
コンストラクタ パラメータは不要です。
メソッドをオーバーライド
アダプタクラスは、ViewPager2 のさまざまなメソッドをオーバーライドする必要もあります。
ViewPagerとの比較:
getCount()ではなく、getItemCount()をオーバーライドします。名前がわからなくても、 このメソッドは変更されません。getItem()ではなく、フラグメント ベースでcreateFragment()をオーバーライドする 使用します。新しいcreateFragment()メソッドが常に は、関数が呼び出されるたびに、新しいフラグメント インスタンスを インスタンスを再利用できます。
概要
まとめると、ViewPager アダプター クラスを ViewPager2 で使用できるように変換するには、次のようにします。
次の変更を行う必要があります。
- ビューのページングを行うには、スーパークラスを
RecyclerView.Adapterに変更します。FragmentStateAdapter: フラグメントのページングに使用します。 - フラグメント ベース アダプター クラスのコンストラクタ パラメータを変更します。
getCount()ではなくgetItemCount()をオーバーライドします。- フラグメント ベースのアダプターで
getItem()ではなくcreateFragment()をオーバーライドする 。
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 から切り離され、
マテリアル コンポーネント。つまり、これを使用するには
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 オブジェクト内でスクロール ビューをサポートするには、次のようにします。
呼び出します
ViewPager2 オブジェクトに対する requestDisallowInterceptTouchEvent()
ネストされた要素がスクロールされるとは限りません。ViewPager2 のネストされたスクロール
サンプルは、この問題を多目的に解決する 1 つの方法を示しています。
カスタム ラッパー レイアウト。
参考情報
ViewPager2 の詳細については、以下の参考リンクをご覧ください。
サンプル
- ViewPager2 サンプル(GitHub)
動画
- ページをめくる: ViewPager2 への移行(Android Dev Summit 2019)