[Android] NestedScrollView Issue
안드로이드 개발을 하다보면 ScrollView 안에 RecyclerView를 넣어야 하는 경우가 생긴다. 이럴 때, NestedScrollView
를 사용하면 된다. 이름처럼 중첩된 스크롤뷰라는 뜻이다. 필자는 NestedScrollView를 아주 유용하게 사용한다. 사용하는 상황은 다음과 같다.
- RecyclerView이 있는데 다른 형태의 뷰가 보여질 때
- 타이틀이 있고 아래에 리스트 목록이 보일 때
두 가지 경우는 거의 비슷하다. 첫 번째 경우는 사실 ViewType을 다르게 하여 RecyclerView를 구성할 수도 있다. 하지만, 이 부분이 조금 번거롭다면 NestedScrollView를 사용하는 것도 하나의 방법이다.
issue
이제 필자가 겪은 문제를 말하려고 한다. 서론이 길었다. 위에서 두 번째 경우를 구현해야 하는 상황이 있었다. NestedScrollView는 ScrollView와 마찬가지로 내부에 ViewGroup을 하나만 가질 수 있다. 그래서 LinearLayout을 두고 그 안에 타이틀을 보여주는 TextView와 리스트를 나타내는 RecyclerView를 두었다.
그런데 경우에 따라서 이 NestedScrollView가 자기 멋대로 밑으로 스크롤이 내려갈 때가 있다. 처음에는 이유를 몰랐다. 그래서 구글링을 해보면서 찾아봤다. 이유는 뷰가 그려지면서 안에 넣어둔 또 다른 ScrollView(즉, 여기서는 RecyclerView)에 포커스가 잡히면서 타이틀이 보이지 않는 것이었다.
그래서 이 포커스를 어떻게 없앨까 찾아보았다. 포커스만 없앤다면 뷰가 그려지면서 RecyclerView에 포커스되는 상황이 없어지고 스크롤이 제멋대로 내려가지 않을테니 말이다. 바로 다음의 한줄만 추가하면 된다.
1 | android:descendantFocusability="blocksDescendants" |
무슨 속성일까?
descendantFocusability
: ViewGroup 내에서 포커스를 맞출 때 ViewGroup과 그의 하위 뷰의 관계를 설정한다. 여기서 하위 뷰란 자식 뷰를 의미한다.blocksDescendants
: 해당 뷰 그룹의 하위 뷰가 포커스를 받지 못하게 하는 옵션이다.
어디에 정의할까?
ScrollView의 자식 뷰에 설정하면 된다. 스크롤뷰는 자식 뷰를 하나만 가지기 때문에 LinearLayout에 설정하면 된다.
xml 코드
1 | <androidx.core.widget.NestedScrollView |
결론
1 | android:descendantFocusability="blocksDescendants" |
정리하면, 위의 설정은 NestedScrollView 안의 자식 뷰(하위 뷰)가 포커스를 가져가는 현상을 막아준다. 즉, NestedScrollView 안에 있는 RecyclerView가 포커스를 가져가지 않는다. 따라서 NestedScrollView는 원하던 대로 포커스를 받고 스크롤이 내려가는 현상도 방지할 수 있다.