【Kotlin】ViewPager vs ViewPager2

#記事を移動しました。
https://zenn.dev/dd_sho/articles/17d670a3dce2d2
今後は上記の記事で更新します。（2021/10/03）

最近 `ViewPager` を使う機会があったので調べたことを備忘録として記事にします。
AndroidXに移行すると `ViewPager2` というViewPagerの改良版が使えるので２つについて書いていきます。

公式のドキュメントはこちら↓↓
[ViewPager](https://developer.android.com/reference/androidx/viewpager/widget/ViewPager?hl=en)
[ViewPager2](https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2?hl=en)

実装方法だけ知りたいよという方はこちらの記事が参考になるかと思います。
[Kotlinでアプリを作ってみる(TabLayout,ViewPager,Fragment,FragmentPagerAdapter)](https://qiita.com/nanamama/items/93ebd9c6a2732cb49777)
[ViewPager2 + TabLayout + DataBinding](https://qiita.com/mii-chang/items/f15301f817121715291e)
# どっちを使うべきか？
名前からイメージがつく通り `ViewPager2` は `ViewPager` の改良版で基本的に `ViewPager2` を使う方が良いと思います（私見です）。

> ViewPager2 is an improved version of the ViewPager library that offers enhanced functionality and addresses common difficulties with using ViewPager.

[移行ガイド](https://developer.android.com/training/animation/vp2-migration) より

（ちなみに、僕のプロジェクトでは `ViewPager2` だと感度が良すぎる（切り替わりが速い）との意見をいただいて結局 `ViewPager` を使うことにしました。現状の `ViewPager2(v1.0.0)` だとその辺のカスタマイズができませんでした。。。）

# ViewPager2 を使うには
次の2stepが必要です。
- AndroidXに移行する
- 依存関係を追加する

```
dependencies {
    implementation "androidx.viewpager2:viewpager2:1.0.0"
}
```

使い方は `ViewPager` とほとんど変わりません。
**レイアウトで配置→Adapterを設定**

```xml
<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />
```
（`ViewPager2` だと縦向きもできます）

# 両者の違い
## Adapter
ここが一番の違いだと思います。
具体的には下記の通りです。

|ViewPager|ViewPager2|
|:-----------------:|:------------------:|
|PagerAdapter|RecyclerView.Adapter|
|FragmentPagerAdapter|FragmentStateAdapter|
|FragmentStatePagerAdapter|FragmentStateAdapter|

大雑把にいうと、 `ViewPager2` では `RecyclerView` がベースになっています。
各Adapterのリンクはこちら↓↓
[PagerAdapter](https://developer.android.com/reference/kotlin/androidx/viewpager/widget/PagerAdapter)
[RecyclerView.Adapter](https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.Adapter)
[FragmentPagerAdapter](https://developer.android.com/reference/kotlin/androidx/fragment/app/FragmentPagerAdapter)
[FragmentStatePagerAdapter](https://developer.android.com/reference/kotlin/androidx/fragment/app/FragmentStatePagerAdapter)
[FragmentStateAdapter](https://developer.android.com/reference/kotlin/androidx/viewpager2/adapter/FragmentStateAdapter)

## TabLayoutとの連携
`ViewPager` では

```kotlin
TabLayout.setupWithViewPager()
```

というメソッドが用意されていましたが、`ViewPager2` では使えません。。
`ViewPager2` では `TabLayoutMediator` を使います。

> you must update the code that attaches the TabLayout object to the ViewPager object. While TabLayout uses its own setupWithViewPager() method to integrate with ViewPager, it requires a TabLayoutMediator instance to integrate with ViewPager2.

[移行ガイド](https://developer.android.com/training/animation/vp2-migration) より

`TabLayoutMediator` を使うためにまず `Material components` を使えるように依存関係を追加します。

```
dependencies {
    implementation "com.google.android.material:material:1.1.0-beta01"
}
```
実際に連携するコードは下記の通りです。

```kotlin
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
        tab.text = "タブのタイトル"
    }.attach()
```
自分で試した範囲だと上記で問題なく連携できそうです。
タブのタイトルの設定がAdapterからこちらに移動してますね。
他にもいろいろ設定できそうです。

ただ、直接は関係ないのですが、 `Material components` のバージョンを上記のようにあげると、僕のプロジェクトの場合はデザインが崩れた箇所があったので要注意です:sob:
# ViewPagerを使う時は
ちなみに `ViewPager` にはonResume()が呼ばれるタイミングにバグがありましたが、Adapterに `BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT` というフラグを設定すると解消します。

```kotlin
class SampleAdapter(
    fm: FragmentManager
) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
    override fun getItem(position: Int): Fragment {
        return SampleFragment.newInstance(position)
    }

    override fun getCount(): Int {
        // ...
    }
}
```
# まとめ
以上、ざっくりですがViewPager関連で調べたことをまとめました。
サンプルコードは既に記事が上がっていたので割愛しました:bow_tone1:
リンクを貼ってあるので参考にしてみてください。
**前半にも書きましたが、基本的にはViewPager2を使うのが良いと思いますが、使用感に少し違いがあるのでUI/UXデザイナーと相談しながら決めた方が良さそうです。**