[Android, Kotlin] RecyclerView 터치 이벤트 두번 호출 문제 해결하기

[문제 상황]

 

안드로이드 스튜디오에서 kotlin으로 일정 관리 앱을 개발 중이었다.

Recycler View에서 item을 클릭했을 때 하단에서 SlidingUpPanelLayout이 아이템별로 다르게 나타나게 했다.

recycler view에 터치 리스너를 달아서 아이템 클릭 이벤트를 intercept 하는 방식으로 터치 리스너를 구현하고 있었는데,

item 클릭 시 sliding layout이 나타나지 않는 경우 등 제대로 동작하지 않는 것 같아서 Log를 찍어보았다.

 

 

[Log 기록 확인]

 

addOnItemTouchListener(object : RecyclerView.OnItemTouchListener{
    override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {

        val child = rv.findChildViewUnder(e.x, e.y)
        if (child != null) {
            val position = rv.getChildAdapterPosition(child)
            Log.d("position","$position")

 

아이템 클릭 시 제대로 position 값을 적용 하는지 확인하기 위해서 Log 기록을 확인했다.

 

item view 클릭 시 정상 동작

 

한번 클릭에 두번 씩 호출됨

 

원하는 대로 동작은 하지만 한번 클릭에 intercept 리스너가 2번씩 호출 된 것을 확인했다.

이를 위한 해결 방법이 필요했다.

 

[해결 방안]

 

이전에 인스타그램 클론코딩을 진행할 때 이미지 뷰를 확대하는 코드를 작성한 적이 있었는데, 

줌 인을 구현하기 위해서 터치 이벤트를 공부한 적이 있었다.

터치 이벤트 중에서는 손가락이 화면에 닿았을때, 떨어졌을 때 두가지 이벤트 감지가 있었는데,

Recycler View에서 item을 클릭 할 때 두 가지 이벤트가 모두 감지되어서 두번 호출 되는 것 같았다.

이는 MotionEvent에 관한 ACTION 조건과 관련이 있는 것 같아서 관련 안드로이드 개발 문서를 확인했다.

MotionEvent  |  Android Developers

 

MotionEvent  |  Android Developers

 

developer.android.com

 

해결 방법은 터치 리스너 동작 시 ACTION_DOWN (화면에 손가락이 닿음) 이벤트 일 때만 인터셉트하고,

ACTION_UP (화면에서 손가락이 떨어짐) 이벤트 일 때는 동작하지 않도록 하는 것이였다.

 

override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
    if (e.action == MotionEvent.ACTION_DOWN) {
        val child = rv.findChildViewUnder(e.x, e.y)
        if (child != null) {
            val position = rv.getChildAdapterPosition(child)
            Log.d("position", "$position")

 

Intercept Event 내부에 화면에 손가락이 처음 닿았을 경우에만 이벤트가 발생하도록 작성했다.

 

이제 한 번만 호출

 

정상적으로 문제를 해결했다.