[Android, Kotlin] ViewPager2의 currentItem 설정이 동작하지 않는 문제
Android

[Android, Kotlin] ViewPager2의 currentItem 설정이 동작하지 않는 문제

원하는 동작 : ImageListFragment에서 RecyclerView의 이미지 리스트 중 하나를 클릭하면

클릭한 이미지의 Position을 받아와 GalleryFragment에서 ViewPager 형태로 해당 이미지를 보여준다.

ViewPager2의 current position을 이미지의 position으로 설정한다.

 

 

 

 

발생한 문제 : current position 설정과 관계 없이 리스트의 첫번째 이미지가 보여진다.

 

기존 코드 : 

// RecyclerViewBinding.kt
@JvmStatic
@BindingAdapter("submitListViewPager")
fun bindSubmitListViewPager(view: ViewPager2, list: Array<RedditImage>) {
    (view.adapter as GalleryPagerAdapter).apply {
        images = list
        notifyDataSetChanged()
    }
}


// fragment_gallery.xml
<androidx.viewpager2.widget.ViewPager2
            android:id="@+id/view_pager"
            app:submitListViewPager="@{images}"
            android:background="@color/black"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

BindingAdapter를 통해 viewPager의 아이템 리스트를 업데이트한다.

 

 

// GalleryFragment
private fun initViews() = with(binding) {
    viewPager.adapter = pagerAdapter
    images = args.images

    val position = args.position
    viewPager.setCurrentItem(position, false)
}

GalleryFragment의 onCreateView 메소드에서 view에 대한 초기화를 수행하는 해당 메소드를 실행한다.

 

이 때 setCurrentItem이 동작하지 않는 이유는 각 line의 실행 타이밍에 있다.

제대로 setCurrentItem이 동작하려면 다음과 같은 순서가 보장되어야 한다.

 

1. images = args.images를 통해 BindingAdapter에서 ViewPager에 image list가 전달되고 리스트가 뷰페이저와 바인딩 된다.

2. ViewPager의 setCurrentItem 메소드가 동작하여 바인딩 된 image list를 기반으로 position이 설정된다.

 

뷰페이저에 바인딩 된 image list를 기반으로 setCurrentItem 메소드가 동작해야한다.

 

하지만 Log를 통해 순서를 확인해보니 다음과 같았다.

 

데이터 바인딩의 submitList 동작보다 setCurrentItem 메소드의 동작이 우선적으로 이루어진다.

그러므로 비어있는 뷰페이저의 리스트에 position이 설정된 뒤 submitList가 동작하여 뒤늦게 리스트가 새로 바인딩 됨으로써 기존에 설정한 current position이 초기화된다.

 

해결 코드 :

ViewPager에 리스트가 바인딩 된 뒤에 setCurrentItem 메소드가 수행 될 수 있도록 position까지 BindingAdapter에 넘겨주고 BindingAdapter에서 setCurrentItem 메소드를 수행 할 수 있도록 하였다.

 

@JvmStatic
@BindingAdapter("submitListViewPager", "currentPosition")
fun bindSubmitListViewPager(view: ViewPager2, list: Array<RedditImage>, position: Int) {
    (view.adapter as GalleryPagerAdapter).apply {
        images = list
        notifyDataSetChanged()
    } // submitList
    view.setCurrentItem(position, false) //set current Item
}

 

BindingAdapter 메소드에 submitList, setCurrentItem 동작을 동기적으로 처리하여 submitList -> setCurrentItem 순서가 보장되었다. 드디어 정상 동작한다.

 

 

 

소스코드 : https://github.com/HunSeongPark/gallerit-clone

 

GitHub - HunSeongPark/gallerit-clone: auron567님의 Gallerit 기반 공부 (Architecture Components, MVVM, Coroutines, Flow, Na

auron567님의 Gallerit 기반 공부 (Architecture Components, MVVM, Coroutines, Flow, Navigation, Retrofit, Room, Hilt) - GitHub - HunSeongPark/gallerit-clone: auron567님의 Gallerit 기반 공부 (Architecture Compone...

github.com