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)