2021年2月25日木曜日

ViewPager2 でページを動的に追加・削除する

大事なポイントは FragmentStateAdapter を継承した Adapter で getItemId() と containsItem() を実装すること、notifyDataSetChanged() だとうまく動かないので DiffUtil.calculateDiff() を使うことです。
class ViewPager2Activity : AppCompatActivity() { private val binding by lazy { ActivityViewPager2Binding.inflate(layoutInflater) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) val list = listOf( PageType.MAIN, PageType.FAVORITE, PageType.SETTING, ) val list2 = listOf( PageType.MAIN, PageType.SETTING, ) val adapter = PagerAdapter(list, this) binding.pager.adapter = adapter TabLayoutMediator(binding.tabLayout, binding.pager) { tab, position -> tab.text = list[position].toString() }.attach() binding.checkbox.setOnCheckedChangeListener { _, isChecked -> adapter.updateList(if (isChecked) list else list2) } } } enum class PageType { MAIN, FAVORITE, SETTING } private class PagerAdapter( initial: List<PageType>, fragmentActivity: FragmentActivity ) : FragmentStateAdapter(fragmentActivity) { private val list = mutableListOf<PageType>() init { list.addAll(initial) } override fun getItemCount(): Int { return list.size } override fun createFragment(position: Int): Fragment { return PageFragment.newInstance(list[position]) } override fun getItemId(position: Int): Long { return list[position].ordinal.toLong() } override fun containsItem(itemId: Long): Boolean { return list.any { it.ordinal.toLong() == itemId } } fun updateList(newList: List<PageType>) { // notifyDataSetChanged() だとうまく動かない val diff = DiffUtil.calculateDiff(object : DiffUtil.Callback() { override fun getOldListSize(): Int { return list.size } override fun getNewListSize(): Int { return newList.size } override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return list[oldItemPosition] == newList[newItemPosition] } override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return list[oldItemPosition] == newList[newItemPosition] } }) list.clear() list.addAll(newList) diff.dispatchUpdatesTo(this) } } class PageFragment : Fragment() { private val color = Color.rgb(Random.nextInt(256), Random.nextInt(256), Random.nextInt(256)) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return TextView(inflater.context).apply { setBackgroundColor(color) text = (requireArguments().getSerializable("type") as PageType).toString() } } companion object { fun newInstance(type: PageType): PageFragment { return PageFragment().apply { arguments = bundleOf("type" to type) } } } }

0 件のコメント:

コメントを投稿