ViewPager2 간단히 사용해보기
안드로이드 ViewPager2의 알파 버전이 2019년 2월 7일에 릴리즈되었다. 새로운 기능으로는 RTL 레이아웃과 수직 스크롤링이 지원되고 기존 ViewPager 버그 수정으로 notifyDataSetChanged
기능이 완전히 동작한다.
샘플 코드 : https://github.com/dudmy/blog-sample
우선 build.gradle에 의존성을 추가한다. ViewPager2는 Android X 용으로 출시되어서 사용하려면 프로젝트가 Android X로 마이그레이션 되어야 한다.
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha01'
그리고 Activity 또는 Fragment에 ViewPager2 위젯을 추가한다.
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
RecyclerView.Adapter
ViewPager2에서는 RecyclerView.Adapter가 PagerAdapter를 대체한다. RecyclerView 사용법과 같기 때문에 별도의 학습비용이 없다는 장점이 있다.
class PagerRecyclerAdapter(private val bgColors: List<Int>) : 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(bgColors[position], position)
}
override fun getItemCount(): Int = bgColors.size
}
class PagerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textView: TextView = itemView.findViewById(R.id.page_name)
fun bind(@ColorRes bgColor: Int, position: Int) {
textView.text = "RecyclerViewAdapter\nPage $position"
itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, bgColor))
}
}
마지막으로 ViewPager2에 어댑터를 설정해주면 된다.
pager.adapter = PagerRecyclerAdapter(bgColors)
pager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
FragmentStateAdapter
FragmentStateAdapter를 이용하면 이전처럼 페이지 아이템을 프래그먼트로 구성할 수 있다. 기존 ViewPager의 FragmentStatePagerAdapter를 대체한 API이다.
class PagerFragmentStateAdapter(private val bgColors: List<Int>, fm: FragmentManager) : FragmentStateAdapter(fm) {
override fun getItem(position: Int): Fragment =
PagerFragment.newInstance(bgColors[position], position)
override fun getItemCount(): Int = bgColors.size
}
class PagerFragment : Fragment() {
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 = "FragmentStateAdapter Page ${it.getInt("position")}"
view.setBackgroundColor(ContextCompat.getColor(view.context, it.getInt("bgColor")))
}
}
companion object {
fun newInstance(@ColorRes bgColor: Int, position: Int): PagerFragment {
val bundle = Bundle()
bundle.putInt("bgColor", bgColor)
bundle.putInt("position", position)
return PagerFragment().apply { arguments = bundle }
}
}
}
이번에는 새롭게 지원되는 수직 스크롤링으로 설정해보았다.
pager.adapter = PagerFragmentStateAdapter(bgColors, supportFragmentManager)
pager.orientation = ViewPager2.ORIENTATION_VERTICAL
OnPageChangeCallback
기존 ViewPager의 addPageChangeListener는 인터페이스여서 메서드를 모두 재정의해야 했다. 하지만 ViewPager2의 OnPageChangeCallback은 추상 클래스이기 때문에 필요한 메서드만 재정의하면 된다.
pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
}
})
이제 첫 번째 릴리즈라서 Known issues가 좀 있지만, 기존 문제점이 많이 보완되고 사용법이 쉽기 때문에 ViewPager2가 ViewPager를 충분히 대체할 수 있을 것 같다.
참고 자료)