- 전체
- 명
- 오늘 찾아주신 분
- 명
롱클릭이야 onTouchEvent 가 아닌 GestureDetector 를 통해서 편하게 옵션을 제공해 줄 수 있지만 내가 필요했던 이벤트는 바로,
특정 위치를 롱클릭 한 후, 상태를 활성화 하여 드래그 하는 것이다.
적당한 예시가 있다면 화면을 길 게 누르면 편집상태가 되어 그 상태에서 손을 떼지 않고 그림을 그린다거나 할 때 쓸 수 있을 것 같다.
드래그 함과 동시에 받아오게 되는 x, y 좌표 값에 따라 invalidate 시킬 예정이었기 때문에 필요한 로직이었다. 여기서의 드래그는 기본적으로 제공해주는 그 Drag 가 아닌 이벤트이다. 그래서 롱클릭 후에 onScroll 이나 onTouchEvent 에서 ACTION_MOVE 를 통해서 처리하면 되지 않을까 하고 구현을 해 보았는데...
롱클릭을 한 후에 다른 모션으로 바로 이어지지 않았다. 롱클릭 후에도 ACTION_MOVE가 계속 들어올 수 있는 줄 알았지만 둘은 별도로 움직일 수 밖에 없어서 손을 화면에서 떼고 다시 붙여야 작동을 했었다. 그거는 일반 ACTION_DOWN 과 다른이 없기 때문에 쓸모가 없어서 어떻게 하는 지 찾아보니 나와 같은 고민들을 하는 사람들이 많았다.
그래서 알아본 결과 다음의 솔루션을 발견할 수 있었다.
private var isLongPressed = false
private val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean = true
override fun onScroll(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float): Boolean = true
override fun onFling(e1: MotionEvent, e2: MotionEvent, vx: Float, vy: Float): Boolean = true
override fun onLongPress(e: MotionEvent) {
if(!isLongPressed)
isLongPressed = true
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean
= event?.run {
if(detector.onTouchEvent(this)) true
else{
when(actionMasked){
MotionEvent.ACTION_MOVE -> {
// 롱 클릭 후 드래그 하기 위해서는 ACTION_MOVE 할 때,
// Cancel 이벤트를 MotionEvent 에 전달해주는 방식으로 트릭을 사용한다고 한다.
if(isLongPressed){
isLongPressed = false
val cancelEvent = MotionEvent.obtain(this).apply {
action = MotionEvent.ACTION_CANCEL
}
detector.onTouchEvent(cancelEvent)
}
}
}
super.onTouchEvent(this)
}
} ?: super.onTouchEvent(event)
롱클릭을 활용하기 위해서 GestureDetector 를 활용하였고, 드래그에 해당 되는 것은 GestureDetector 의 onScroll 을 통해서 관리할 수 있었다. 로직의 프로세스는 다음과 같다.
- 롱 클릭 이벤트를 GestureDetector 로 받는다. 롱 클릭이 들어왔다는 것을 onTouchEvent 에서도 확인해야 하기 때문에 플래그를 사용한다.
- onTouchEvent 에서 action 값이 ACTION_MOVE 인 상태를 받아준다. 단, 롱 클릭 이후에 들어온 ACTION_MOVE 를 받기 위해서 플래그를 이용하여 일반 ACTION_MOVE 와 걸러줄 수 있도록 한다.
- 걸러진 이벤트가 하나 들어오게 되면, 해당 이벤트의 action 을 ACTION_CANCEL 로 변경한 후, GestureDetector 에 전달한다. 이 다음부터 onScroll 에서 터치를 받고 움직이는 감도를 받을 수 있다.
DragListener 라는 것이 View 에도 존재하긴 하지만, 다른 방식의 드래그가 필요한 경우헤는 사용할 만 한 로직인 것 같아 남겨두도록 한다.
[Android] 다음 주소 찾기 서비스를 편하게 사용하기 (1) | 2023.11.23 |
---|---|
Groovy 에서 KTS 로 변경하기 (1) | 2023.01.26 |
[Android] Logcat 에서 보고 싶은 태그만 필터링하기 (0) | 2022.05.16 |
[Android] Web 에서 App 으로 데이터를 받아보자 (0) | 2022.02.04 |
[Android] Glide with PDF -3(완결)- (0) | 2022.02.04 |