ViewPager2の特徴
- RTL レイアウトのサポート
- 縦スクロールのサポート
- 既存の
ViewPager
のNotifyDataSetChanged
のバグ修正
実装
ViewPager2はAndroidx
対応なので、プロジェクトをAndroidx
にマイグレーションする必要があります。
build.gradleに追加
build.gradle
dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta04'
}
xmlにViewPager2を追加
Activity
またはFragment
にViewPager2を追加します。
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical" />
RecyclerView.Adapter
ViewPager2はPagerAdapter
の代わりにRecyclerView.Adapter
を使います。RecyclerView
と使い方は同じなので別途に学習する必要がないメリットがあります。
class PagerRecyclerAdapter(private val items: List<String>) : RecyclerView.Adapter<PagerViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerViewHolder =
PagerViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_pager, parent, false))
override fun onBindViewHolder(holder: PagerViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
}
class PagerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textView: TextView = itemView.findViewById(R.id.page_name)
fun bind(text: String) {
textView.text = text
}
}
Adpaterを設定
最後にViewPager2にAdapter
を設定します。
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)
viewpager2.adapter = PagerRecyclerAdapter(items)
viewpager2.orientation = ViewPager2.ORIENTATION_HORIZONTAL
}
}
縦スクロールの実装
次は新しくサポートされた縦スクロールの実装をしてみます。
FragmentStateAdapter
FragmentStateAdapter
を利用すれば前のようにページアイテムをFragment
に構成できます。既存のViewPager
のFragmentStatePageAdapter
に代わるAPI
です。
viewpager2.adapter = object : FragmentStateAdapter(this) {
override fun getItemCount(): Int = items.size
override fun createFragment(position: Int) = PagerFragment.newInstance(items[position])
}
viewpager2.orientation = ViewPager2.ORIENTATION_VERTICAL
PagerFragment
class PagerFragment : Fragment() {
companion object {
fun newInstance(text: String): PagerFragment = PagerFragment().apply {
arguments = Bundle().apply {
putString("text", text)
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.item_pager, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.let {
page_name.text = it.getString("text")
}
}
}
OnPageChangeCallback
既存のViewPager
のAddPageChangeListener
はインタフェース
なので、各メソッドを再定義する必要がありました。
しかしViewPager2
のOnPageChangeCallback
は抽象クラス
なので、必要なメソッドだけ再定義すれば良いです。
viewpager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
}
})