주요 내용으로 건너뛰기

안드로이드 탭 터치 이벤트 가로채기

물론 Design Support Library TabLayout 얘기

안드로이드 머티리얼 디자인의 컴포넌트 중에 Tabs라는 항목이 있다. 각 탭 별로 화면을 구성하도록 할 수 있는 뷰 컴포넌트를 설명하고 있는 문서인데, Android에서 이 뷰를 구현하도록 도와주는 Design Support Library에 TabLayout이라는 클래스로 등록이 되어있다. TabLayout의 사용법은 안드로이드 개발자 문서의 이 곳에서 볼 수 있다.


귀찮으니까 여기서부터는 어지간한 영어도 그냥 한글로 표기하도록 하겠다. 여튼 이 탭 레이아웃은 기본적으로 탭을 클릭하면 해당 탭에 등록되어있는 뷰를 보여주는 용도로 쓰게 되어있는데, 앱 기획에 의해 특정 탭을 클릭했을 경우 화면 내에 지정된 뷰를 보여주는게 아니라 다른 동작을 수행하도록 해야하는 일이 생겼다. 처음에는 '뭐 그정도야' 하고 뷰페이저의 뷰는 네개, 탭은 다섯개를 만들어 특정 탭에만 뷰를 보여주는 이벤트를 제외하는 식으로 구현했다. 그런데 아뿔사, 탭 레이아웃의 하단에 있는 탭 인디케이터가 문제였던 것이다. 탭 인디케이터는 탭 레이아웃의 최하단에 위치하여 현재 어떤 탭에 있는지를 알려주는 것인데, 잘 모르겠다면 다음 gif(출처)를 보자.


왔다갔다 하는 하얀 줄이 탭 인디케이터이다.


뷰를 보여주지 않더라도 탭을 터치했을때 저 밑의 하얀 줄이 해당 탭으로 이동하는게 영 눈에 거슬리는게 문제였던 것이다. 말로만 들으면 어떨지 모르겠는데, 실제로 보면 너무 이상해보였던 것. 그래서 좀 찾아보니 이런 해결책을 찾을 수 있었다. 이 해결책은 모든 탭의 터치 이벤트를 흡수하고 있기 때문에 조금 바꿔서 구현하면 다음과 같다.



적용해보니 확실히 되는데, 도대체 이게 어떻게 되는거지 하고 탭 레이아웃의 코드를 들여다 보니 LinearLayout을 상속하는 SlidingTabStrip이라는 내부 클래스가 있고 이게 탭 터치에 따른 탭 인디케이터의 움직임을 주관하고 있는 것 같았다. 인디케이터 위치에 따른 스크롤까지 해주는것 같은데 거기까지 보긴 좀 귀찮아서...여튼 인디케이터 움직임의 모든 것을 주관하는 모양이다. 그리고 TabLayout의 생성자를 보면 이 슬라이딩 탭 스트립을 가장 최초로 뷰에 집어넣고 있는 것을 볼 수 있다.



저 코드상의 mTabStrip이 슬라이딩 탭 스크립 객체의 변수이고, 모든 생성자가 저 위의 생성자 코드를 가리키고 있기 때문에 무조건 탭레이아웃의 첫번째 자식뷰가 된다. 그렇기 때문에 저 위의 코드에서 getChildAt(0)으로 탭 스트립을 불러올 수 있었던 것. 그리고 다음 코드를 보면 탭 레이아웃의 addTabView 메소드가 호출될 때마다 이 mTabStrip에 해당 tabView가 추가되고 있는 것을 볼 수 있다.


 

그런고로 이 mTabStrip의 자식 뷰 중에서 원하는 녀석의 인덱스를 통해 터치 이벤트를 가로채기가 가능했던 것. 다만 문제가 있다면 Design Support Library가 업데이트될 때마다 TabLayout의 코드가 변하진 않았는지 확인해봐야 한다는 것이다. 불안하긴 하지만 일단은 이 방법밖에 없는 것 같으니 어쩔수 없을듯. 그래도 탭 뷰를 하나하나 직접 구현하는 것보단 훨씬 낫지 않나.


#Android #Material #Design #TabLayout #안드로이드 #머티리얼 #디자인 #탭레이아웃

안드로이드 애플리케이션 개발자

구본욱 님의 창작활동을 응원하고 싶으세요?

댓글

SNS 계정으로 간편하게 로그인하고 댓글을 남겨주세요.
#15
안드로이드 7.0(N)의 기능과 공개일
#17
UIScrollView에서 Swipe Gesture 사용하기