-
Android 이벤트 리스너의 기원.....과연 어디까지 가는것인가Android📱 2022. 3. 5. 14:53
미션 프로젝트를 달성하던중 궁금증이 생김
터치 이벤트를 사용해야하는데
적용이 안되는 것이다.
그래서 이벤트처리에 대해서 실험을 해보기로 마음을 먹고 새프로젝트 생성!
일단 간단하게 실험을 할거라서 화면에 텍스트를 표기하는 기능만 추가
커스텀 뷰를 만들고 거기서 터치이벤트를 받아 보기로했다.
(그리고 커스텀뷰와 액티비티에 모든 생명주기에 로그를 추가했다)
일단 터치 이벤트만 구현해보기
Custom View의 터치 이벤트
override fun onTouchEvent(event: MotionEvent?): Boolean { Log.d("myCustom", "onTouch") when (event!!.action) { MotionEvent.ACTION_DOWN -> { str = "눌렀다." Log.d("myCustom", "down") } MotionEvent.ACTION_MOVE -> { str = "움직인다" Log.d("myCustom", "move") } else -> { str = "뭐하냐?" performClick() Log.d("myCustom", "else") } } return super.onTouchEvent(event) }
Main Activity의 터치 이벤트
override fun onTouchEvent(event: MotionEvent?): Boolean { val custom = findViewById<Custom>(R.id.cus) when(event!!.action){ MotionEvent.ACTION_DOWN -> { custom.str = "down" Log.d("myActivity", "down") } MotionEvent.ACTION_MOVE -> { custom.str = "move" Log.d("myActivity", "move") } else -> { custom.str = "??" custom.performClick() Log.d("myActivity", "else") } } return super.onTouchEvent(event) } }
아마 하시는 분들은 벌써 코드가 안될거라는게 보이실거다.
일단 실험해보자아무리 클릭하고 터치를 해도 아무일도일어나지 않는다
왜 그럴까?
로그를 확인해보자계속 Down을 누른것만 받고 onDraw를 해주지 않는다.
텍스트는 바꿔었지만 화면을 다시 그리지 않아서 일어나는 문재이다.그러면 어떻게 해야할까?
바로 invalidate()를 호출해 주어야한다.
어디에 호출하는게 좋을까?
일단 커스텀 뷰에 넣어보자.else -> { elseMsg() performClick() // notice("ELSE") Log.d("myCustom", "down") } } invalidate() return super.onTouchEvent(event) }
커스텀 뷰의 리턴위에다가 올려보자
else -> { custom.str = "??" custom.performClick() Log.d("heungActivity", "??") } } custom.invalidate()
클릭을 했더니 바꿔었다.
하지만 무브와 다른 이벤트가 동작하지 않는다.
여기가 아닐까?
이번에는 액티비티에서 해보자오! 된다.
뭐띾 왜 커스텀 뷰는 안되고 액티비티에서는 되는 것일까
답은 리턴 값에 있다.아마 눈썰미가 좋은 분이면 커스텀뷰와 액티비티에서 각각 다른 이벤트가 일어난것을 알 수 있을것이다.
커스텀 뷰에서는 한글로 텍스틑를 바꿨는데 메인 액티비티에서는 영어와 ??로 바꾸는 코드를 사용하였다.
그런데 결과를 보면 한글은 보이지도 않고 액티비티의 동작만 일어났다.로그를 확인해보면 커스텀 뷰에서 다운을 부르고 바로 액티비로 가서 move가 나올때는 계속 draw만 하는 것을 알 수 있다.
바로 리턴값이 super.onTouchEvent(event) 이기 때문이다.
아마 여기 시골 블로그까지 오신 분들이라면... 여기 저기 예제 코드도 많이 보셨으리라 예상한다.
예제 코드를 보면 어떤 코드는 true를 반환하고 어떤 코드는 super.onTouchEvent(event)를 반환하는 걸 볼 수있다.
커스텀 뷰에서 true를 반환하면else -> { elseMsg() performClick() Log.d("myCustom", "else") } } invalidate() return true }
- 커스텀 뷰에 invalidate()를 추가해야한다
그러면 커스텀 뷰에서 적용한 항목만 실행이 된다.
바로 super를 사용하면 상위 뷰로 터치이벤트를 옮겨가기 때문이다.
그래서 커스텀 뷰에서 적용한 효과는 액티비티에서 바뀌게 된다.
그래서 만약 커스텀뷰에서 뭔가 변화를 주고 싶다면 return을 true로 반환하고
액티비티에서 처리하고 싶다면 super.onTouchEvent(event)를 반환해주면된다.오늘의 삽질 끝....
혹시 틀린 점이나 이상한점은 댓글로 피드백주시면 수정하겠습니다...아직 허접이라 ㅠㅠ
'Android📱' 카테고리의 다른 글
[안드로이드 오류] Cannot resolve symbol (0) 2022.03.12 [Adroid] Live Data 실험해보기 (0) 2022.03.09 [Android] Call Back 함수공부 (0) 2022.03.06 [kotlin] interface Listener로 event listener 구현해보기 (0) 2022.03.04 안드로이드 View의 생명주기 (0) 2022.03.03