정상에서 IT를 외치다

[Android, Double Scroll] 이중 스크롤 어떻게 구성하면 좋을까? 본문

안드로이드

[Android, Double Scroll] 이중 스크롤 어떻게 구성하면 좋을까?

Black-Jin 2019. 3. 8. 11:16
반응형


안녕하세요. 블랙진입니다.


ScrollView 안에 ListView 혹은 RecyclerView 가 있는 이중 스크롤에 관한 포스팅입니다.


cf) 제가 사용한 RecyclerView 예제는 이 링크에서 받을 실 수 있습니다.



1. 처음 생각이 드는 ScrollView 안에 RecyclerView 구조


preview


xml code

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<RelativeLayout
android:background="@android:color/holo_blue_bright"
android:layout_width="match_parent"
android:layout_height="300dp">

<TextView
android:layout_centerInParent="true"
android:text="BlackJin Tistory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</RelativeLayout>

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</LinearLayout>

</ScrollView>

ScrollView 안에는 자식뷰를 단 1개만 가질 수 있습니다. 이에 LinearLayout 을 설정하여 TextView 1개 있는 레이아웃과 그 아래 RecyclerView를 달아보았습니다. 어떻게 동작을 할까요?



BlcakJin Tistory 부분을 스크롤 하면 ScrollVIew 가 동작되고 RecyclerView 를 스크롤 하게 되면 RecyclerView 의 스크롤이 움직입니다.




1. 처음 앱을 시작 할 때 상단뷰의 일부가 가려저 있습니다. (리사이클러뷰의 일부가 위로 올라와 있다)


이는 RecycleView 에서 아이템을 그리는 과정에서 아이템에 포커싱이 되어 ScrollView 가 말려 올라가는 현상입니다. 리사이클러뷰로 가는 포커싱을 막아줌으로서 해결할 수 있습니다.

<!-- 자식뷰의 포커싱을 막아주는 blocksDescendants 를 추가해 줍니다. -->
<LinearLayout
android:descendantFocusability="blocksDescendants"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

ConstantValueDescription
afterDescendants1The ViewGroup will get focus only if none of its descendants want it.
beforeDescendants0The ViewGroup will get focus before any of its descendants.
blocksDescendants2The ViewGroup will block its descendants from receiving focus.

AndroidVIewGroup - blacksDescendants




2. ScrollView 와 RecyclerView 의 스크롤이 따로따로 동작한다.


이중 스크롤에서 가장 큰 문제가 바로 각각의 스크롤이 따로 동작한다는 것입니다. 이를 알아서 해결해 주는 NestedScrollView 를 사용해 주면 됩니다.


NestedScrollView 에 관한 구글 문서에는 이렇게 적혀 있습니다.


NestedScrollView is just like ScrollView, but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.


ScrollView 와 동작은 같으나 부모와 자식 둘다 중첩된 스크롤링 액션을 지원해준다!


동작원리에 관해 궁금하신 분은 이에 관한 영문 포스터가 있으니 참고해 주세요.



3. Solution

<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:descendantFocusability="blocksDescendants"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<RelativeLayout
android:background="@android:color/holo_blue_bright"
android:layout_width="match_parent"
android:layout_height="300dp">

<TextView
android:layout_centerInParent="true"
android:text="BlackJin Tistory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</RelativeLayout>

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</LinearLayout>

</android.support.v4.widget.NestedScrollView>

두가지 Solution을 모두 적용해 위와 같이 작업해 주면 이중 스크롤뷰 안에 리사이클러뷰를 구현 하실 수 있습니다.




cf) 이중 스크롤뷰 안에 리사이클러 뷰를 사용하게 되면 리사이클러뷰는 아이템을 전부 미리 생성하게 됩니다. (RecyclerView Adapter 의 onBindViewHolder 에서 로그를 찍어보시면 확인하실 수 있습니다.) 또한 Item View 를 재활용 하지 않기 때문에 View 를 재사용하여 메모리 효율을 높일 수 있다는 리사이클러뷰의 큰 이점을 잃어버리게 되니 꼭 참고해서 사용해 주셔야 합니다. 아이템이 많은 경우에는 사용을 지양합니다.

반응형
Comments