스타일러스 손바닥 움직임 무시

별 5개 평점 아이콘

스타일러스는 생산성과 창의성이 뛰어난 도구가 될 수 있습니다. 하지만 사용자는 스타일러스를 사용하여 앱에서 그리거나 쓰거나 상호작용할 때 손바닥으로 화면을 터치하기도 합니다. 시스템이 이러한 이벤트를 의도치 않은 손바닥 터치로 인식하여 무시하기 전에 터치 이벤트가 앱에 보고될 수 있습니다.

권장사항

앱은 관련 없는 터치 이벤트를 식별하여 무시해야 합니다. Jetpack Compose에서는 기본 Android MotionEvent에서 PointerEvent 액세스할 수 있습니다. 동작이 중지되어야 하고 롤백해야 할 수 있음을 나타내는 MotionEvent에 ACTION_CANCEL를 확인합니다. Android 13 (API 수준 33) 이상에서는 FLAG_CANCELED 플래그 를 ACTION_CANCEL 및 ACTION_POINTER_UP 이벤트에서 확인합니다. 이 플래그는 손바닥 터치와 같이 터치가 의도치 않았다는 강력한 신호를 제공합니다.

재료

  • Modifier.pointerInput(): 포인터 입력을 처리하는 데 사용되는 Compose 수정자입니다.
  • PointerEvent: 변경사항이 하나 이상 포함된 Compose의 포인터 이벤트를 나타냅니다.
  • PointerEvent.motionEvent: 기본 Android MotionEvent (nullable)에 액세스할 수 있는 확장 속성입니다.
  • MotionEvent: 터치 및 이동 이벤트를 나타냅니다. 이벤트를 무시할지 결정하는 데 필요한 정보가 포함되어 있습니다.
  • ACTION_CANCEL: 동작이 취소되었음을 나타내는 MotionEvent 상수입니다. 동작이 중지되어야 하고 롤백해야 할 수 있습니다.
  • ACTION_POINTER_UP: 첫 번째 포인터 이외의 포인터가 위로 올라갔다고, 즉 기기 화면과의 접촉을 포기했다고 나타내는 MotionEvent 상수입니다.
  • FLAG_CANCELED: 포인터가 위로 올라가 의도치 않은 터치 이벤트가 발생했음을 나타내는 MotionEvent 상수입니다. Android 13 (API 수준 33) 및 이후 버전의 ACTION_POINTER_UP 및 ACTION_CANCEL 이벤트에 추가되었습니다.

단계

앱에 전달된 MotionEvent 객체를 검사합니다. MotionEvent API를 사용하여 이벤트 특성을 판단합니다.

  • 단일 포인터 이벤트 : 동작이 중지되어야 함을 나타내는 ACTION_CANCEL을 확인합니다. Android 13 이상에서는 터치가 의도치 않았음을 확인하기 위해 FLAG_CANCELED도 확인합니다.
  • 멀티 포인터 이벤트 : Android 13 이상에서는 의도치 않은 터치를 식별하기 위해 ACTION_POINTER_UP 및 FLAG_CANCELED를 확인합니다.

동작을 중지하고 임시 변경사항을 롤백하여 이러한 이벤트에 응답합니다.

1. 모션 이벤트 객체 획득

Modifier.pointerInput을 사용하여 컴포저블에서 포인터 입력을 처리합니다. 포인터 입력 범위 내에서 awaitPointerEventScope 및 awaitPointerEvent를 사용하여 이벤트를 수신하고 기본 Android MotionEvent를 motionEvent 속성을 사용하여 검색합니다.

import androidx.compose.ui.input.pointer.pointerInput
    Box(
        modifier = Modifier
            .fillMaxSize()
            .pointerInput(Unit) {
                awaitPointerEventScope {
                    while (true) {
                        val event = awaitPointerEvent()
                        val motionEvent = event.motionEvent
                        if (motionEvent != null) {
                            // Process motion event.
                        }
                    }
                }
            }
    )

2. 이벤트 작업 및 플래그 확인

모든 API 수준에서 단일 포인터 이벤트를 나타내는 ACTION_CANCEL에 MotionEvent를 확인합니다. Android 13 이상에서는 FLAG_CANCELED에 ACTION_POINTER_UP을 확인합니다.

import androidx.compose.ui.input.pointer.pointerInput
    Box(
        modifier = Modifier
            .fillMaxSize()
            .pointerInput(Unit) {
                awaitPointerEventScope {
                    while (true) {
                        val event = awaitPointerEvent()
                        val motionEvent = event.motionEvent ?: continue

                        when (motionEvent.actionMasked) {
                            MotionEvent.ACTION_CANCEL -> {
                                // Process canceled single-pointer motion event for all SDK versions.
                            }
                            MotionEvent.ACTION_POINTER_UP -> {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
                                    (motionEvent.flags and MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED
                                ) {
                                    // Process canceled multi-pointer motion event for Android 13 and higher.
                                }
                            }
                        }
                    }
                }
            }
    )

3. 동작 실행취소

손바닥 터치를 식별한 후에는 동작이 화면에 미치는 효과를 실행취소할 수 있습니다.

손바닥 터치와 같은 의도하지 않은 입력이 실행취소될 수 있도록 앱에서는 사용자 작업 기록을 유지해야 합니다. 예를 보려면 기본 그리기 앱 구현을(를) Android 앱에서 스타일러스 지원 개선 Codelab에서 참고하세요.

결과

이제 앱은 Android 13 이상 API 수준의 멀티 포인터 이벤트와 모든 API 수준의 단일 포인터 이벤트에서 손바닥 터치를 식별하고 무시할 수 있습니다.

추가 리소스

자세한 내용은 다음을 참고하세요.