본문 바로가기
깡샘 코틀린

08-1 터치와 키 이벤트

by 농농씨 2023. 6. 22.

터치 이벤트

앱의 화면에서 발생하는 사용자 이벤트는 터치(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