After ADS ’19: Migrating to ViewPager2
AndroidDevSummit 세션 내용을 간단히 정리해봅니다.
ViewPager2의 부가적인 기능
기존 ViewPager에서 지원하지 않던 기능들이 ViewPager2에서는 제공되고 있다. (지원할 수 없었던 것은 아닐까? 🤔)
- Vertical Scrolling 지원
android:orientation="vertical" - RTL 지원
android:layoutDirection="rtl" - Modifiable Fragment collections
- DiffUtil
내부적으로 RecyclerView 기반으로 구현되어 있어서,
DiffUtil도 지원한다. - New developement only in ViewPager2
앞으로는 ViewPager2에만 신규 기능이 추가된다고 한다.
따라서 ViewPager1을 사용하던 코드가 유지보수 되어야 한다면, ViewPager2로 전환하는 것을 고려해봐야 할 것 같다.
Migration Guide
전환을 고려할 수 있게 가이드가 제공되고 있다.
- RecyclerView.Adapter를 상속하는 형태로 변경된다.
// ViewPager
class MyAdapter : PagerAdapter()
// ViewPager2
class MyAdapter : RecyclerView.Adapter<...>()- Item Count를 정의하는 부분이 달라진다.
// ViewPager
override fun getCount(): Int {...}// ViewPager2
override fun getItemCount(): Int {...}
- Fragment Adapter가 변경된다.
// ViewPager
class MyFragmentAdapter(
fm: FragmentManager
) : FragmentStatePagerAdapter(fm, ...)
// ViewPager2
class MyFragmentAdapter(
fa: FragmentActivity
) : FragmentStateAdapter(fa)// orclass MyFragmentAdapter(
fm: FragmentManager,
l: Lifecycle
) : FragmentStateAdapter(fm, l)
- Adapter에서 Fragment 생성하기
// ViewPager
override fun getItem(position: Int): Fragment {...}
// ViewPager2
override fun createFragment(position: Int): Fragment {...}TabLayout와의 결합
MDC 1.1.0에서 ViewPager2와 연결할 수 있는 Component를 제공한다. 기존의 ViewPager Adapter는 fun getPageTitle(position: Int)를 구현해야 했지만, ViewPager2는 별도의 API로 Configuration을 설정할 수 있다.
// build.gradle
implementation "com.google.android.material:material:1.1.0-beta01"// Fragment - with ViewPager
tabLayout.setupWithViewPager(viewPager)// Fragment - with ViewPager2
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = "Item ${(position + 1)}"
}.attach()
후기
얼마 전에 개인 앱에 시험삼아 ViewPager를 ViewPager2로 교체해보니, API가 크게 변경되지 않았지만 이름은 다 변경이 되서 약간씩 손을 봐야 했다.
개인적으로 TabLayoutMediator를 사용하는 코드가 썩 예쁘진 않은 듯 해서, 아래와 같은 코드를 추가하여 코드 개선을 시도해봤다. 참고해보세요.
interface TitleProvider {
fun getItemTitle(position: Int): CharSequence
}fun TabLayout.setupWithViewPager2(
viewPager2: ViewPager2,
titleProvider: TitleProvider,
autoRefresh: Boolean
) {
TabLayoutMediator(this, viewPager2, autoRefresh,
TabLayoutMediator.TabConfigurationStrategy { tab, position ->
tab.text = titleProvider.getItemTitle(position)
}
).attach()
}// Use like this
tabLayout.setupWithViewPager2(
viewPager, titleProvider = pageAdapter, autoRefresh = true)
