Отказ от стилуса

значок пятизвездочного рейтинга

Стилус может быть исключительно продуктивным и творческим инструментом. Но когда пользователи рисуют, пишут или взаимодействуют с приложением с помощью стилуса, они иногда касаются экрана ладонью. Событие касания может быть передано вашему приложению до того, как система распознает и отклонит его как случайное касание ладонью.

Передовые методы

Ваше приложение должно распознавать посторонние события касания и игнорировать их. В 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 (допускается значение null).
  • MotionEvent : Представляет события касания и движения. Содержит информацию, необходимую для определения того, следует ли игнорировать событие.
  • ACTION_CANCEL : Константа MotionEvent , указывающая на отмену жеста; жест должен быть остановлен и, возможно, потребуется его откатить.
  • ACTION_POINTER_UP : Константа MotionEvent , указывающая на то, что указатель, отличный от первого, поднялся (то есть, перестал контактировать с экраном устройства).
  • FLAG_CANCELED : Константа MotionEvent , указывающая на то, что движение указателя вверх вызвало непреднамеренное касание. Добавляется к событиям ACTION_POINTER_UP и ACTION_CANCEL в Android 13 (уровень API 33) и выше.

Шаги

Изучите объекты MotionEvent , отправленные в ваше приложение. Используйте API MotionEvent для определения характеристик событий:

  • События, связанные с одним указателем — проверьте наличие 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 на наличие 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. Отмените жест.

Как только вы определите касание ладонью, вы сможете отменить действие жеста на экране.

Ваше приложение должно хранить историю действий пользователя, чтобы можно было отменить непреднамеренные действия, такие как касания ладонью. Пример можно найти в разделе «Реализация базового приложения для рисования» в практическом руководстве по улучшению поддержки стилуса в приложении Android .

Результаты

Теперь ваше приложение может распознавать и отклонять касания ладонью при одновременном использовании нескольких указателей на Android 13 и более поздних версиях API, а также при одновременном использовании одного указателя на всех уровнях API.

Дополнительные ресурсы

Для получения более подробной информации см. следующие материалы: