このエントリはVersion 1.0.0-alpha01 に基づいて記述しています。
今朝、androidx.viewpager2:viewpager2 が公開された。
従来の 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
実装は RecyclerView と PagerSnapHelper の組み合わせによるもので、これ自体は以前から一つの組み合わせパターンとして知られていたものだった。今回 ViewPager2 という widget としてそれが用意された、と捉えてよさそう。そして RecyclerView なので orientation を渡すことができる。いつも通りの感覚で水平、垂直、任意の方向にスクロールする UI を作れる。
サンプル
簡単なサンプルを作った。
特別に説明するような項目はないように見えたので、ソースコードに書いたコメントを参考にしてほしい。
// 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()) } }) }