BottomSheetDialog에서 ViewPager2, RecyclerView, NestedScrollView를 함께 사용할 때 겪은 문제 해결

kingori

Sewon Ann

Posted on June 9, 2020

BottomSheetDialog에서 ViewPager2, RecyclerView, NestedScrollView를 함께 사용할 때 겪은 문제 해결

며칠 간 나를 괴롭히던 문제들을 어제 드디어 해결했다.

BottomSheetDialog 안에 복잡한 UI가 들어간다. 상태에 따라 RecyclerView , NestedScrollView, ViewPager2 가 보였다 사라졌다 한판 흥겨운(...) 축제의 한마당이 펼쳐진다.

3가지 문제가 있었다.

1. 스크롤이 잘 안된다.

첫 화면은 ViewPager2 가 등장한다. 상태가 바뀌어 ViewPager2 가 gone 되고 RecyclerView 가 visible 한다. 근데 RecyclerView 스크롤이 안되는 것도 아니고, 잘 되는 것도 아니고 묘하게 버벅인다.

이전에도 NestedScrollView 와 RecyclerView 가 서로 왔다리갔다리 할 때 문제를 겪었다. 당시엔 현재 보이는 뷰에 isNestedScrollEnabled 를 true로, 보이지 않는 뷰엔 false로 주어 그나마 간단하게 해결했다.

하지만 이번엔 온갖 속성 (enabled, isNestedScrollEnabled 등등)을 주어봐도 제대로 해결이 되지 않았다. 자세히 살펴보니 좀 희안한 속성이 있었다. 이미 화면에서 사라진 ViewPager2 가 있었던 자리에선 스크롤이 잘 되고, 그 바깥 자리에선 스크롤이 안된다.

그래서 이런 말도 안되는 더미 뷰를 넣어봤다. 문제가 해결되었다. 왜 그런진 모르겠다 -_-;

<ConstraintLayout>
 <androidx.core.widget.NestedScrollView
        android:id="@+id/dummy"
        android:visibility="invisible"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="0dp"
        android:layout_height="0dp" />
 ...
</ConstraintLayout>

2. TabLayout을 이용해 표현한 ViewPager2의 indicator가 제대로 안보임

ViewPager2를 이용해 dot indicator를 보여주려면 좀 꼼수를 부려야 한다. 나는 Android ViewPager(2) with dots indicator에서 소개한 방식을 썼다. TabLayout을 사용하고, 탭의 배경을 조정해서 보여줬다. 잘 동작했다.

문제는 이 TabLayoutViewPager2가 사라질 때 사라지고, 나타날 때 다시 나타나야 하는데, 다시 나타날 때 스크롤 위치를 제대로 표현하지 못했다. 항목이 아주 많을 경우 스크롤 포지션을 제대로 못잡는다. 물론 이렇게 항목이 많다면 ViewPager를 쓰는게 맞는지 UI 구성부터 다시 해야 하지만, 극히 예외적인 경우에 대한 테스트용도였다.

이것도 엄청 삽질을 하다 결국 찾아낸 솔루션은 TabLayoutViewPager2의 연결을 끊었다 다시 붙이는 방법이었다.

val tabLayoutMediator =
                TabLayoutMediator( tabLayout, viewPager2) { _, _ -> }

//초기에 붙였다가
tabLayoutMediator.attach()

//viewPager2 gone 될 때 떼었다가
tabLayoutMediator.detach()

//viewPager2 visible 될 때 다시 붙인다.
tabLayoutMediator.attach()

아 정말...

3. ViewPager2 의 좌우 항목이 안보인다.

ViewPager 시절부터 좌우 항목을 살짝 보이게 만들 수 있었다. ViewPager2 에선 PageTransformer를 통해 더 확장성이 좋지만 조금은 더 어렵게 구현할 수 있따. 이 내용은 ViewPager2 파헤치기 이 글을 따라하면 쉽게 구현할 수 있다.

문제는 ViewPager2 가 다시 나타날 경우이다. 다시 나타날 때 저 PageTransformer가 제대로 적용이 되지 않은 상태로 나타나서, 좌우 항목이 안보이다 살짝 손을 대면 갑자기 튀어나온다.

이건 ViewPager2.requestTransform() 메서드를 써서 해결했다. 하지만 제대로 보였다 안보였다 문제가 있었다. 이 경우엔 그냥 마법의 30ms 딜레이를 주던지, 다른 layout callback을 쓰던지 해서 해결할 수 있을 것 같다. 나는 일단은 마법의 30ms 딜레이를 주었다.

viewPager.postDelayed(30) {
 viewPager.requestTransform()
}

일단 여기까지 해서 스크롤, dot indicator, page transform 문제는 다 해결이 되었다. 이 문제 해결하느라 한 5일 정도 쓴 것 같다. 안드로이드 개발 힘들어요 ㅠㅠ

💖 💪 🙅 🚩
kingori
Sewon Ann

Posted on June 9, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related