タッチペンは、生産性と創造性を高める優れたツールです。しかし、ユーザーがタッチペンを使用して描画、書き込み、またはアプリの操作を行うと、手のひらが画面に触れることがあります。このタッチイベントが、手のひらでの偶発的なタッチとして認識されて無視される前に、アプリに報告される場合があります。
ベスト プラクティス
アプリは、不要なタッチイベントを識別して無視する必要があります。Jetpack
Compose では、基盤となる Android MotionEvent から a
PointerEvent にアクセスできます。MotionEvent で ACTION_CANCEL を確認します。これは
操作を停止してロールバックする必要があることを示します。Android 13(API レベル 33)以降では、FLAG_CANCELED フラグを ACTION_CANCEL イベントと ACTION_POINTER_UP イベントで確認します。これは、手のひらでのタップなど、タッチが意図しないものであったことを示す強力なシグナルです。
材料
Modifier.pointerInput(): ポインタ入力を処理するために使用される Compose 修飾子。PointerEvent: Compose のポインタ イベントを表します。これには 1 つ以上の変更が含まれます。PointerEvent.motionEvent: 基盤となる AndroidMotionEvent(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_UPとFLAG_CANCELEDを確認して、意図しないタッチを識別します。
これらのイベントに応答するには、操作を停止して、一時的な変更をロールバックします。
1. モーション イベント オブジェクトを取得する
Modifier.pointerInput を使用して、Composable でポインタ入力を処理します。ポインタ入力スコープ内で、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. イベント アクションとフラグを決定する
MotionEvent を確認します。これは、すべての API レベルでのシングル ポインタ
イベントを表します。ACTION_CANCELAndroid 13 以降では、ACTION_POINTER_UP で FLAG_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 レベルにおけるシングルポインタ イベントで、手のひらでのタップを識別、拒否できるようになりました。
参考情報
詳しくは次の記事をご覧ください。
- Android 13 の機能と API - パーム リジェクションを改善する
- デベロッパー ガイド
- 高度なタッチペン機能
- パーム リジェクションに関する大画面での入力の互換性のセクション
- Codelab - Android アプリでのタッチペン サポートの強化