728x90
반응형
안드로이드 개발을 하다 보면 뷰페이저 안의 아이템 레이아웃의 변경사항이 적용되야 하는 경우가 있다.
하지만 뷰페이저는 페이지를 미리 그려놓기 때문에 레이아웃의 변경사항이 바로 변경되지 않는다.
이를 해결하기 위해서 뷰페이저와 페이지 변경 리스너에서 약간의 조치(?)를 해놓는다.
나의 경우에는 뷰페이저 안에 리사이클러 뷰로 커스텀 달력을 만들었고 페이지를 넘길 때 마다 달이 넘어가게 만들었는데 옆으로 넘겨도 달이 넘어가지 않는 문제가 생겼다.
private fun onPageChangeListener(
viewModel: PlannerViewModel
): ViewPager.OnPageChangeListener {
return object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
override fun onPageSelected(position: Int) {
println("position = ${position}")
when {
position < index -> {
println("calendar.get(Calendar.MONTH) = ${selectedCalendar.get(Calendar.MONTH)}")
println("month -1 ")
selectedCalendar.set(
Calendar.MONTH,
selectedCalendar.get(Calendar.MONTH) - 1
)
viewModel.month.value = selectedCalendar.get(Calendar.MONTH).toString()
viewModel.year.value = selectedCalendar.get(Calendar.YEAR).toString()
Planner.setDays(viewModel)
index = position
refresh()
}
position > index -> {
println("month + 1")
selectedCalendar.set(
Calendar.MONTH,
selectedCalendar.get(Calendar.MONTH) + 1
)
viewModel.month.value = selectedCalendar.get(Calendar.MONTH).toString()
viewModel.year.value = selectedCalendar.get(Calendar.YEAR).toString()
Planner.setDays(viewModel)
index = position
refresh()
}
else -> {
println("month")
selectedCalendar.set(Calendar.MONTH, selectedCalendar.get(Calendar.MONTH))
viewModel.month.value = selectedCalendar.get(Calendar.MONTH).toString()
viewModel.year.value = selectedCalendar.get(Calendar.YEAR).toString()
Planner.setDays(viewModel)
index = position
refresh()
}
}
}
// 데이터의 변경점을 알려줌
fun refresh() {
mViewPagerAdapter.notifyDataSetChanged()
}
}
}
위의 refresh와 같이 어뎁터를 전역으로 설정한 뒤 notifyDataSetChanged()를 붙여 데이터의 변경을 알려준다. 그 후
class PlannerViewPagerAdapter(
fragmentManager: FragmentManager,
private val size: Int
) : FragmentStatePagerAdapter(fragmentManager, size) {
override fun getCount(): Int = size
override fun getItem(position: Int): Fragment {
return Planner2Fragment()
}
// 추가됨
override fun getItemPosition(`object`: Any): Int {
return PagerAdapter.POSITION_NONE
}
}
위와 같이 getItemPosition을 추가한다.
위 함수의 역할은 문서를 읽어보면 아래와 같이 나와있는데
/**
* Called when the host view is attempting to determine if an item's position
* has changed. Returns {@link #POSITION_UNCHANGED} if the position of the given
* item has not changed or {@link #POSITION_NONE} if the item is no longer present
* in the adapter.
*
* <p>The default implementation assumes that items will never
* change position and always returns {@link #POSITION_UNCHANGED}.
*
* @param object Object representing an item, previously returned by a call to
* {@link #instantiateItem(View, int)}.
* @return object's new position index from [0, {@link #getCount()}),
* {@link #POSITION_UNCHANGED} if the object's position has not changed,
* or {@link #POSITION_NONE} if the item is no longer present.
*/
public int getItemPosition(@NonNull Object object) {
return POSITION_UNCHANGED;
}
아이템의 포지션이 변경되는지 아닌지 호스트 뷰가 확인하려고 할 때 호출되는것 같다. 만약 주어진 항목의 위치가 변경되지 않았거나 더 이상 존재하지 않을 경우 POSITION_UNCHANGED를 반환하고 만약 아이템이 더 이상 어뎁터에서 대표되지 않을 때 POSITION_NONE을 반환한다. 즉, 페이지가 바뀔 때 POSITION_NONE을 반환하게 함으로써 전체 뷰를 다시 그리게 만들고 이로 인해 레이아웃을 다시 그리게 되는 것 같다.
설명을 이해하는 것만 해도 엄청 어려운것 같다.. --;;
728x90
반응형