ViewPagerとPagerAdapterでスワイプビューを作ってみる

# 内容
ViewPagerをとPagerAdapter使って、右に左にひゅいっとスワイプして遷移するビューの練習です。
Tabによる遷移も加えておきました。

# 作るもの
すごく単純。ネズミさんから始まりイノシシさんで終わります。
数字の表示が崩れているのはご勘弁を。
![zodiac.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226693/2b2f46a2-ac38-d52d-05cd-3c3e3f51679c.gif)

# ポイント
### ViewPagerとTabLayoutを定義
ポイントと言うほどのものでもないですが、ViewGroupとTabLayoutを定義します。

```xml:activity_zodiac_pager.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager.widget.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/view_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>
```

### PagerAdapterをセット
スワイプビューを作成するためにPagerAdapterをViewPagerにセットします。
adapterなので、RecyclerView.Adapterにちょっと似てますね。
PageAdapterには3つのメソッドが定義されています。

- getCount()
全体の数を取得する

- getItem(position)
指定した位置にあるFragmentを返す

- getPageTitle(position)
指定した位置にあるTab用の表示を返す

### FragmentPagerAdapterの特徴
ここではPageAdapterの実装として **FragmentPagerAdapter** を使っています。
役割をほぼ同じですが、一方で **FragmentStatePagerAdapter** というのもあります。
これらの違いと使い方は以下のような感じ。

||特徴      |使い所|
|:-----------------|:------------------:|:------------------:|
| FragmentStatePagerAdapter|前後のページ以外はメモリから破棄される| 表示する数が多いもの(とりあえずこっちが安全かも) |
| FragmentPagerAdapter|メモリが破棄されず残る |       固定で少ないもの(Tab系はこっちが良さげ?)      |
今回は12個で固定だったので、FragmentPagerAdapterを使いました。
（12個は多い部類説？）

FragmentStatePagerAdapterにおいてデフォルトでは前後の1ページですが、`setOffscreenPageLimit(int)` によってロードする前後のページ数を調整できます。


```kotlin:ZodiacPagerActivity.kt
class ZodiacPagerActivity : AppCompatActivity() {

    private lateinit var mViewPager: ViewPager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_zodiac_pager)

        mViewPager = findViewById(R.id.view_pager)

        val fragmentManager = supportFragmentManager
        mViewPager.adapter = object : FragmentPagerAdapter(fragmentManager) {
            override fun getItem(i: Int): Fragment {
                val fragment = ZodiacFragment()
                fragment.arguments = Bundle().apply {
                    putInt(ARG_OBJECT, i)
                }
                return fragment
            }

            override fun getCount(): Int {
                return 12
            }

            override fun getPageTitle(position: Int): CharSequence? {
                return "${position + 1}"
            }

        }
    }
}

private const val ARG_OBJECT = "object"

class ZodiacFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_zodiac, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val textView: TextView = view.findViewById(R.id.zodiacText)
        val i = arguments?.getInt(ARG_OBJECT)
        textView.text = getAnimalName(i)
    }

    private fun getAnimalName(i: Int?): String {
        return when (i) {
            0 -> "子"
            1 -> "丑"
            2 -> "寅"
            3 -> "卯"
            4 -> "辰"
            5 -> "巳"
            6 -> "午"
            7 -> "未"
            8 -> "申"
            9 -> "酉"
            10 -> "戌"
            11 -> "亥"
            else -> "神"
        }
    }
}
```

# 参考
[Create swipe views with tabs](https://developer.android.com/guide/navigation/navigation-swipe-view)
[Android Programming: The Big Nerd Ranch Guide (3rd Edition) (Big Nerd Ranch Guides)](https://amzn.to/2K8OlO7)