【Android】画面コンポーネント / ViewPager2

■ はじめに

https://dk521123.hatenablog.com/entry/2019/09/28/020307

の続き。
今回は、ViewPager2 について、学ぶ。

■ 作成手順

* ViewPager / ViewPager2 どちらでも基本は同じで以下の通り。

1)Fragmentを追加・実装する
2)Activityに ViewPager を追加する
 ⇒ その際に、id を設定する
3)Adapterを実装する
4)2)のActivityを実装する

■ 環境設定

以下を追加し、
Android Studioの[Build]-[Rebuild Project]を選択し、ビルドする

build.gradle (Module:app)

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

■ サンプル

例1:Hello world

1)Fragmentを追加・実装する 
 => 以下「SampleFragment.kt」を参照

2)Activityに ViewPager2 を追加する
 ⇒ id「mainViewPager」

3)Adapter(RecyclerView.Adapterを継承)を実装する
 => 以下「SampleAdapter.kt」を参照

4)2)のActivityを実装する
 => 以下「MainActivity.kt」を参照

SampleFragment.kt

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

class SampleFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

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

SampleAdapter.kt

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class SampleAdapter(private val items: List<String>) : RecyclerView.Adapter<PagerViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerViewHolder {
        return PagerViewHolder(
            LayoutInflater.from(parent.context).inflate(
                R.layout.fragment_sample, parent, false
            )
        )
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: PagerViewHolder, position: Int) {
        holder.bind(items[position])
    }
}

class PagerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val textView: TextView = itemView.findViewById(R.id.sampleFragment)

    fun bind(text: String) {
        textView.text = text
    }
}

MainActivity.kt

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager2.widget.ViewPager2
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private val items: MutableList<String> = mutableListOf(
        "Page 1",
        "Page 2",
        "Page 3",
        "Page 4"
    )

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

        mainViewPager.adapter = SampleAdapter(items)
        mainViewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
    }
}

例2:例1の別解

SampleFragment.kt (TextView を追加)

mport android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_sample.view.*

class SampleFragment : Fragment() {
    private var text = ""

    companion object {
        @JvmStatic
        fun newInstance(position: Int, text: String): SampleFragment {
            val fragment = SampleFragment()
            val bundle = Bundle()
            bundle.putString("Position", position.toString())
            bundle.putString("Text", text)
            fragment.arguments = bundle
            return fragment
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.text = arguments?.getString("Text") +
                " " + arguments?.getString("Position")
    }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.textView.setText(text)
    }
}

SampleAdapter.kt

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter

class SampleAdapter(
    fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {
    private val items: MutableList<Int> = mutableListOf()

    override fun getItemCount(): Int {
        return items.count()
    }

    override fun createFragment(position: Int): Fragment {
        this.items.add(position)
        return SampleFragment.newInstance(position, "Hello world")
    }
}

MainActivity.kt

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.widget.ViewPager2
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        this.initializeViewPager(mainViewPager)
    }

    private fun initializeViewPager(pager: ViewPager2?) {
        val adapter = SampleAdapter(this.supportFragmentManager, this.lifecycle)
        adapter.createFragment(0)
        adapter.createFragment(1)
        adapter.createFragment(2)
        adapter.createFragment(3)
        pager?.adapter = adapter
    }
}

関連記事

画面遷移をするには
https://dk521123.hatenablog.com/entry/2013/09/26/010117
ボタンイベントを処理するには
https://dk521123.hatenablog.com/entry/2013/09/25/002349
別画面への値の受け渡し
https://dk521123.hatenablog.com/entry/2013/09/27/230328
画面コンポーネント / ViewPager ~ リストをスワイプして切替 ~
https://dk521123.hatenablog.com/entry/2019/09/28/020307
画面コンポーネント / TabLayout
https://dk521123.hatenablog.com/entry/2020/08/18/000000