터치 이벤트
앱의 화면에서 발생하는 사용자 이벤트는 터치(touch)이다. 터치란 손가락으로 화면을 잠시 눌렀다가 떼는 행위를 말한다. 앱은 사용자의 터치를 인식하고 화면을 손가락으로 눌렀는지, 떼었는지, 스와이프(swipe, 화면에 손가락을 댄 상태로 쓸어넘기는 동작)했는지 따라 알맞게 동작하도록 구현한다.
이처럼 앱의 화면에서 발생하는 사용자의 터치 이벤트를 처리하고 싶다면 액티비티 클래스에 터치 이벤트의 콜백 함수인 onTouchEvent()를 선언하면 된다.
✅콜백함수란? 어떤 이벤트가 발생하거나 시점에 도달했을 때 자동으로 호출하는 함수.
// 터치 이벤트 처리
class MainActivity : AppCompatActivity() { // 액티비티 클래스에
(...생략...)
override fun onToucnEvent(event: MotionEvent?): Boolean { // 터치이벤트의 콜백함수를 선언함
return super.onTouchEvent(event)
}
}
액티비티에 onTouchEvent() 함수를 재정의(override)해서 선언만 해놓으면 사용자가 이 액티비티 화면을 터치하는 순간 onTouchEvent() 함수가 자동으로 호출된다. onTouchEvent()함수에 전달되는 매개변수는 MotionEvent 객체이며, 이 객체에 터치의 종류와 발생 지점(좌푯값)이 담긴다.
터치 이벤트의 종류
터치 이벤트는 다음 3가지로 구분된다.
- ACTION_DOWN: 화면을 손가락으로 누른 순간의 이벤트
- ACTION_UP: 화면에서 손가락을 떼는 순간의 이벤트
- ACTION_MOVE: 화면을 손가락으로 누른 채로 이동하는 순간의 이벤트
만약 화면을 손가락으로 살짝 눌렀다가 떼었다면 onTouchEvent() 함수는 2번 호출된다.
첫번째는 ACTION_DOWN, 그 다음은 ACTION_UP 이벤트가 호출된다.
만약 화면을 터치해서 손가락을 이동한 후 떼었다면
처음에 ACTION_DOWN, 이동하면서 ACTION_MOVE 이벤트가 계속 발생하다가 손가락을 떼는 순간 ACTION_UP 이벤트가 발생한다.
// 터치 이벤트 처리
override fun onTouchEvent(event: MotionEvent?): Boolean { // 액티비티에서 콜백함수 재정의 선언
when (event?.action) {
MotionEvent.ACTION_DOWN -> { // 화면 누르면 실행
Log.d("kkang", "Touch down event")
}
MotionEvent.ACTION_UP -> { // 화면 떼면 실행
Log.d("kkang", "Touch up event")
}
}
return super.onTouchEvent(event) // super가 뭐였더라~~~
}
터치 이벤트 발생 좌표 얻기
터치 이벤트를 처리할 때는 이벤트 종류뿐만 아니라 이벤트가 발생한 지점을 알아야 하는 경우도 있다. 이 좌표도 onTouchEvent()함수의 매개변수의 MotionEvent 객체로 얻는다.
- x: 이벤트가 발생한 뷰의 X좌표
- y: 이벤트가 발생한 뷰의 Y좌표
- rawX: 화면의 X좌표
- rawY: 화면의 Y좌표
// 터치 이벤트가 발생한 좌표 얻기
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
Log.d("kkang",
"Touch down event x: ${event.x}, rawX: ${event.rawX}") // 매개변수로 좌표 얻음
}
}
return super.onTouchEvent(event)
}
x와 rawX 모두 좌푯값이지만 의미하는 바는 다르다. x는 터치 이벤트가 발생한 뷰에서의 좌푯값, raw는 스크린, 즉 화면에서의 좌표값이다.
따라서 액티비티에 onTouchEvent() 함수를 재정의해서 작성했다면 x와 rawX의 값은 차이가 없다. 그런데 터치 이벤트는 특정 뷰에서도 처리할 수 있으므로 onTouchEvent() 함수를 어떤 뷰에 재정의했다면 x와 raw의 값은 차이가 있다.
키 이벤트
키 이벤트는 사용자가 폰의 키를 누르는 순간에 발생한다. 액티비티에서 키 이벤트를 처리하려면 다음과 같이 콜백함수를 재정의해야 한다. 그러면 키 이벤트가 발생할 때 해당 함수가 자동으로 호출된다.
onKeyDown: 키를 누른 순간의 이벤트
onKeyUp: 키를 떼는 순간의 이벤트
onKeyLongPress: 키를 오래 누르는 순간의 이벤트
// 키 이벤트 처리
class MainActivity2 : ApppCompatActivity() {
(...생략...)
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // 함수 재정의, 키 누를 때 처리
Log.d("kkang", "onKeyDown")
return super.onKeyDown(keyCode, event)
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { // 키 뗄 때 처리
Log.d("kkang", "onKeyUp")
return super.onKeyUp(keyCode, event)
}
}
키 이벤트 함수의 첫번째 매개변수는 키의 코드이며 이 값으로 사용자가 어떤 키를 눌렀는지 식별할 수 있다.
// 어떤 키를 눌렀는지 식별
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_0 -> Log.d("kkang", "0 키를 눌렀네요") // 매개변수로 키의 코드 사용
KeyEvent.KEYCODE_A -> Log.d("kkang", "A 키를 눌렀네요")
}
return super.onKeyDown(keyCode, event)
}
그런데 이러한 키 이벤트가 발생하는 키는 폰에서 제공하는 소프트 키보드의 키를 의미하지 않는다.(!!)
앱에서 글을 입력할 때 화면 아래에서 올라오는 키보드를 소프트 키보드(soft keyboard)라고 한다.
소프트 키보드의 키는 키 이벤트로 처리할 수 없다. 즉, 액티비티에 onKeyDown() 등의 함수를 선언해 놓더라도 사용자가 소프트 키보드의 키를 눌렀을 때 이벤트 함수가 호출되지 않는다. 소프트 키보드는 안드로이드 시스템에 등록된 앱으로서 키를 누르면 글은 입력되지만 키 이벤트는 발생하지 않는다.
그렇다면 키 이벤트는 '의미 없지 않을까?'라고 생각할 수 있다. 하지만 하드웨어 키보드가 있는 기기는 키보드의 키를 누르면 키 이벤트로 처리할 수 있다. 또한 안드로이드 시스템 버튼도 키로 취급하므로 이 버튼의 이벤트를 처리하는 데도 사용된다.
안드로이드 폰은 전원버튼과 볼륨 조절 버튼을 대부분 가지고 있다. 뒤로가기, 홈, 오버뷰(최근에 사용한 앱 목록)도 있고 이 세 버튼을 포함하는 영역을 내비게이션 바(navigation bar)라고 한다. 내비게이션 바는 실행되는 앱과 상관없이 안드로이드 자체에서 제공하는 시스템 바이다.
이 중에서 뒤로가기 버튼과 볼륨조절 버튼은 '키'로 취급해 이벤트로 처리할 수 있다. 그러나 전원, 홈, 오버뷰 버튼은 액티비티에 onKeyDown() 함수를 선언해 놓아도 사용자가 버튼을 눌렀을 때 함수가 호출되지 않는다. 즉, 앱에서 이벤트를 처리할 수 없는 버튼이다.
// 뒤로가기 버튼과 볼륨 조절 버튼의 이벤트 처리
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_BACK -> Log.d("kkang", "BACK Button을 눌렀네요") // 키 이벤트를 처리함
KeyEvent.KEYCODE_VOLUME_UP -> Log.d("kkang", "Volume Up 키를 눌렀네요")
KeyEvent.KEYCODE_VOLUME_DOWN -> Log.d("kkang", "Volume Down 키를 눌렀네요")
}
return super.onKeyDown(keyCode, event)
}
특별히 뒤로가기 버튼 이벤트에는 앞에서 살펴본 onKeyDown()이나 onKeyUp() 함수를 이용할 수도 있지만 onBackPressed() 함수를 이용할 수도 있다.
// 뒤로가기 버튼의 이벤트 처리
override fun onBackPressed() { // onKeyDown 함수 말고 다른 함수 씀
Log.d("kkang", "Back Button을 눌렀네요")
}
그리고 API Level 33에서 뒤로 가기 버튼 이벤트 처리 함수인 OnBackPressed 함수는 deprecated 되었다. 현재는 androidx.activity.OnBackPressedCallback() 함수 이용을 권장하고 있으므로 이후 실습에서 deprecated() 메시지가 나오면 참고하길 바란다.
// 뒤로가기 버튼의 이벤트 처리
OnbackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
}
})
'깡샘 코틀린' 카테고리의 다른 글
09-1 리소스의 종류와 특징 (0) | 2023.06.23 |
---|---|
08-2 뷰 이벤트 (0) | 2023.06.23 |
07-5 계층 구조로 배치 - ConstraintLayout (0) | 2023.06.20 |
07-4 표 형태로 배치 - GridLayout (0) | 2023.06.20 |
07-3 겹쳐서 배치 - FrameLayout (0) | 2023.06.20 |