본문 바로가기

ANDROID/UI - UX

[안드로이드 | 코틀린 ] 뷰가 겹치는 상황에서 터치 우선순위 관리하기

보통 이런저런 상호작용이 들어가는 UI/UX 를 개발하다 보면

 

겹치는 뷰로 인해 골머리가 썩게 되기 마련이다.

 

 

이번 경우에는 BottomSheetBehavor가 적용된 Layout과 부모뷰인 SwipeRefreshLayout간의 간섭으로 인해 생기는 이슈였는데,

 

펼쳐진 자식뷰가 Swipe 가능한 부모뷰를 전부 덮게 되면서, 스와이프로 내릴 수 있는 자식 뷰를 내리지 못하고

 

부모뷰를 통째로 스와이프 해버리게 되어

 

 

결론적으로 펼쳐지고 나서는 접을 수가 없는 상황이 생겨버렸다.

 

 

나빼고

 

 


 

 

터치 이벤트의 우선순위를 조정이 가능하단 것은 인지하고 있었는데, 이를 어떻게 지정해주어야 하는가?

 

검색끝에 깔끔한 해결책을 찾을 수 있었다.

 

 

우선순위를 두고자 하는 뷰에 onTouchListener를 넣어 특정 조건에서 부모 뷰에 requestDisallowInterceptTouchEvent(true)를

 

지정해주면 해결되는 것이었다. 

 

// firstPriorityView는 자식뷰로 secondPriorityView내에 들어가있는 자식 뷰이다.

firstPriorityView.setOnTouchListener { v, event -> 

        // firstPriorityView가 펼쳐졌을 경우에만 부모뷰를 전부 가리게 되기 때문에
        // BottomSheetBehavior state가 접힌 상태로 되어있지 않을 경우에만
        // 부모뷰로 가는 터치 이벤트를 막고자 했다.
    
	if (bottomSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED) {
    	secondPriorityView.requestDisallowInterceptTouchEvent(true)
        
        return@setOnTouchListener false
    }
    
    false
}

 

여기에다 테스트 중 손을 뗐다 붙였다 하는 식의 동작을 거치다 보니 포커스가 다시 부모뷰로 넘어가는 이슈가 있었는데

 

이를 위해 추가적으로 부모뷰의 TouchListener까지 달아주고 나니 완벽하게 뷰 터치 충돌을 막아낼 수 있었다!

 

// 터치중 손을 떼게 되어 포커스가 풀린 상황에서 다시 터치를 할 경우를 방지하기 위함임
secondPriorityView.setOnTouchListener { v, event -> 
	
	// return 뒤에 원하는 조건을 넣어 조건이 true일 경우 터치를 방지하게 된다.
	return@setOnTouchListener bottomSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED
    
    false
}

 

 

< 참조 >

 

Increasing touch priority of a SeekBar

I have a SeekBar inside a HorizontalScrollView and am finding it very hard to grab the handle and move it. If I don't touch exactly on the handle, the HorizontalScrollView will receive and consume ...

stackoverflow.com