タッチペンは、生産性と創造性に優れたツールです。しかし、ユーザーがタッチペンを使用して描画、書き込み、またはアプリの操作を行うと、手のひらが画面に触れることがあります。このタッチイベントが、手のひらでの偶発的なタッチとして認識されて無視される前に、アプリに報告される場合があります。
ベスト プラクティス
アプリは、不要なタッチイベントを識別して無視する必要があります。Jetpack Compose では、PointerEvent から基盤となる Android の MotionEvent にアクセスできます。MotionEvent で ACTION_CANCEL を確認します。これは、ジェスチャーを停止してロールバックする必要がある可能性があることを示します。Android 13(API レベル 33)以降では、ACTION_CANCEL イベントと ACTION_POINTER_UP イベントで FLAG_CANCELED フラグを確認します。このフラグは、手のひらでのタッチなど、意図しないタッチであったことを示す強力なシグナルを提供します。
材料
Modifier.pointerInput(): ポインタ入力の処理に使用される Compose 修飾子。PointerEvent: 1 つ以上の変更を含む Compose のポインタ イベントを表します。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 を使用して、コンポーザブルのポインタ入力を処理します。ポインタ入力スコープ内で、awaitPointerEventScope と awaitPointerEvent を使用してイベントを受信し、motionEvent プロパティを使用して基盤となる Android 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 で ACTION_CANCEL を確認します。これは、すべての API レベルでのシングル ポインタ イベントを表します。Android 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 アプリでのタッチペン サポートの強化