タッチペンのパーム リジェクション

5 つ星評価アイコン

タッチペンは、生産性と創造性を高める優れたツールです。しかし、ユーザーがタッチペンを使用して描画、書き込み、またはアプリの操作を行うと、手のひらが画面に触れることがあります。このタッチイベントが、手のひらでの偶発的なタッチとして認識されて無視される前に、アプリに報告される場合があります。

ベスト プラクティス

アプリは、不要なタッチイベントを識別して無視する必要があります。Jetpack Compose では、基盤となる Android MotionEvent から a PointerEvent にアクセスできます。MotionEventACTION_CANCEL を確認します。これは 操作を停止してロールバックする必要があることを示します。Android 13(API レベル 33)以降では、FLAG_CANCELED フラグを ACTION_CANCEL イベントと ACTION_POINTER_UP イベントで確認します。これは、手のひらでのタップなど、タッチが意図しないものであったことを示す強力なシグナルです。

材料

  • Modifier.pointerInput(): ポインタ入力を処理するために使用される Compose 修飾子。
  • PointerEvent: Compose のポインタ イベントを表します。これには 1 つ以上の変更が含まれます。
  • PointerEvent.motionEvent: 基盤となる Android MotionEvent(null 可能)にアクセスできる拡張プロパティ。
  • 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_UPFLAG_CANCELED を確認して、意図しないタッチを識別します。

これらのイベントに応答するには、操作を停止して、一時的な変更をロールバックします。

1. モーション イベント オブジェクトを取得する

Modifier.pointerInput を使用して、Composable でポインタ入力を処理します。ポインタ入力スコープ内で、awaitPointerEventScopeawaitPointerEvent を使用してイベントを受信し、基盤となる Android MotionEventmotionEvent プロパティを使用して取得します。

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. イベント アクションとフラグを決定する

MotionEvent を確認します。これは、すべての API レベルでのシングル ポインタ イベントを表します。ACTION_CANCELAndroid 13 以降では、ACTION_POINTER_UPFLAG_CANCELED を確認します。

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. 操作を元に戻す

手のひらでのタップを識別した場合、操作による画面上の効果を元に戻すことができます。

手のひらでのタップなどの意図しない入力を元に戻すには、アプリでユーザー操作の履歴を保持する必要があります。例については、基本的な描画アプリを実装する Codelab の Android アプリでのタッチペン サポートの強化をご覧ください。

結果

アプリは、Android 13 以降の API レベルにおけるマルチポインタ イベントと、すべての API レベルにおけるシングルポインタ イベントで、手のひらでのタップを識別、拒否できるようになりました。

参考情報

詳しくは次の記事をご覧ください。