ViewPager2 1.0.0-alpha01 を使うサンプルを書いた

このエントリはVersion 1.0.0-alpha01 に基づいて記述しています。

今朝、androidx.viewpager2:viewpager2 が公開された。

developer.android.com

従来の ViewPager は PagerAdapter を使って Fragment の表示をシームレスに切り替えられものだった。それに TabLayout を組み合わせて TabLayout のアイテムタップ、ViewPager のエリアをスワイプすることで表示を切り替えるような UI を実現する目的に使う、例えば、リスト表示をする複数画面を切り替えたり、拡大表示した画像を別の画像表示に切り替える、等だと思う。

ViewPager2 になると、FragmentStateAdapter は使わず FragmentStateAdapter に、PagerAdapter は使わず RecyclerView.Adapter に置き換えることになる。

API changes

・FragmentStateAdapter replaces FragmentStatePagerAdapter
・RecyclerView.Adapter replaces PagerAdapter
・registerOnPageChangeCallback replaces addPageChangeListener

android.googlesource.com

実装は RecyclerView と PagerSnapHelper の組み合わせによるもので、これ自体は以前から一つの組み合わせパターンとして知られていたものだった。今回 ViewPager2 という widget としてそれが用意された、と捉えてよさそう。そして RecyclerView なので orientation を渡すことができる。いつも通りの感覚で水平、垂直、任意の方向にスクロールする UI を作れる。

サンプル

簡単なサンプルを作った。
特別に説明するような項目はないように見えたので、ソースコードに書いたコメントを参考にしてほしい。

github.com

f:id:bps_tomoya:20190208233131g:plain

// MainActivity.kt から抜粋
// ViewPager2 のセットアップ
private fun setupMainViewPager2() {
  this.main_view_pager2.adapter = MainViewPagerAdapter(this.videoPrograms)
  this.setMainViewPagerOrientation(ViewPager2.ORIENTATION_HORIZONTAL)
  this.main_view_pager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageScrollStateChanged(state: Int) {
      // スクロール状態が切り替わると呼ばれる
      //
      // SCROLL_STATE_IDLE     = 0; => スクロールを待機
      // SCROLL_STATE_DRAGGING = 1; => スクロールが開始した
      // SCROLL_STATE_SETTLING = 2; => 表示する画面が決定された
      super.onPageScrollStateChanged(state)
      Log.d("$tag: onPageScrollStateChanged", state.toString())
    }
    // スクロールイベントが発生している最中リアルタイムに呼ばれる
    //
    // position             => 現在の position が渡される
    //                         スクロールが完了して直前と違う position になっているとその値が反映される
    // positionOffset       => スクロール開始前からの相対的な offset 値
    // positionOffsetPixels => スクロール開始前からの相対的な offset 値(ピクセル)
    //
    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
      super.onPageScrolled(position, positionOffset, positionOffsetPixels)
      Log.d(
        "$tag: onPageScrolled",
        "position => $position, positionOffset => $positionOffset, positionOffsetPixels => $positionOffsetPixels"
      )
    }
    // スクロールが終了すると選択されたページの position を引数にして呼ばれる
    override fun onPageSelected(position: Int) {
      super.onPageSelected(position)
      Log.d("$tag: onPageSelected", position.toString())
    }
  })
}