Android поддерживает различные сенсорные экраны и сенсорные панели, включая графические планшеты со стилусом.
Сенсорные экраны – это сенсорные устройства, связанные с дисплеем таким образом, что у пользователя создается впечатление, будто он напрямую манипулирует элементами на экране.
Сенсорные панели – это сенсорные устройства, не связанные с экраном, например графический планшет. Сенсорные панели обычно используются для указания или абсолютного косвенного позиционирования, а также для управления пользовательским интерфейсом с помощью жестов.
На сенсорных устройствах могут быть кнопки, выполняющие те же функции, что и кнопки мыши.
Сенсорными устройствами можно управлять с помощью различных инструментов, например пальцев или стилуса, в зависимости от технологии, используемой в сенсоре.
Сенсорные устройства иногда используются для реализации виртуальных клавиш. Например, на некоторых устройствах Android сенсорная область экрана выходит за его границы и используется как часть сенсорной клавиатуры.
Из-за большого разнообразия сенсорных устройств Android использует множество свойств конфигурации, чтобы описать характеристики и желаемое поведение каждого устройства.
Классификация сенсорных устройств
Устройство ввода классифицируется как устройство с поддержкой мультисенсорного ввода, если выполняются оба следующих условия:
- Устройство ввода сообщает о наличии абсолютных осей
ABS_MT_POSITION_XиABS_MT_POSITION_Y. - У устройства ввода нет кнопок геймпада. Это условие устраняет неоднозначность, связанную с некоторыми геймпадами, которые сообщают об осях с кодами, совпадающими с кодами осей MT.
Устройство ввода классифицируется как устройство с поддержкой одиночного касания, если выполняются оба следующих условия:
- Устройство ввода не классифицируется как устройство с поддержкой мультисенсорного ввода. Устройство ввода может быть классифицировано как устройство с поддержкой одного касания или как устройство с поддержкой нескольких касаний, но не оба одновременно.
- Устройство ввода сообщает о наличии абсолютных осей
ABS_XиABS_Y, а также о наличии кода клавишиBTN_TOUCH.
Если устройство ввода классифицируется как сенсорное, наличие виртуальных клавиш определяется попыткой загрузить файл сопоставления виртуальных клавиш для устройства. Если доступна виртуальная карта клавиш, также загружается файл раскладки клавиш для устройства. Информацию о местоположении и формате этих файлов можно найти в разделе [Файлы виртуальной раскладки клавиатуры](#virtual-key-map-files).
Затем система загружает файл конфигурации устройства ввода для сенсорного устройства.
У всех встроенных сенсорных устройств должны быть файлы конфигурации устройств ввода. Если файл конфигурации устройства ввода отсутствует, система выбирает конфигурацию по умолчанию, подходящую для сенсорных устройств общего назначения, таких как внешние сенсорные экраны USB или Bluetooth HID или сенсорные панели. Эти значения по умолчанию не предназначены для встроенных сенсорных экранов и могут привести к неправильной работе.
После загрузки конфигурации устройства система классифицирует устройство ввода как сенсорный экран, сенсорную панель или указательное устройство.
- Устройство с сенсорным экраном используется для прямого взаимодействия с объектами на экране. Пользователь напрямую касается экрана, поэтому системе не нужно предоставлять дополнительные возможности для указания объектов, с которыми он взаимодействует.
- Сенсорная панель передает приложению информацию об абсолютном положении касаний в заданной области датчика. Это может быть полезно для графических планшетов.
- Указатель используется для косвенного управления объектами на экране с помощью курсора. Пальцы интерпретируются как жесты указателя с несколькими касаниями. Другие инструменты, например стилусы, интерпретируются с использованием абсолютных координат. Подробнее о жестах непрямого мультисенсорного управления…
При классификации устройства ввода как сенсорного экрана, сенсорной панели или указывающего устройства используются следующие правила:
- Если задано свойство
touch.deviceType, тип устройства будет установлен в соответствии с ним. - Если устройство ввода сообщает о наличии свойства
INPUT_PROP_DIRECT(через ioctlEVIOCGPROP), то тип устройства устанавливается как сенсорный экран. Это условие предполагает, что устройства прямого ввода прикосновением подключены к дисплею, который также подключен. - Если устройство ввода сообщает о наличии свойства ввода
INPUT_PROP_POINTER(черезEVIOCGPROPioctl), то для типа устройства устанавливается значение pointer. - Если устройство ввода сообщает о наличии относительных осей
REL_XилиREL_Y, то тип устройства устанавливается как сенсорная панель. Это условие устраняет неоднозначность для устройств ввода, состоящих из мыши и сенсорной панели. В этом случае сенсорная панель не используется для управления указателем, поскольку это уже делает мышь. - В остальных случаях используется значение pointer. Это значение по умолчанию гарантирует, что сенсорные панели, которым не назначено никаких других специальных функций, управляют указателем.
Кнопки
Кнопки – это необязательные элементы управления, которые приложения могут использовать для выполнения дополнительных функций. Кнопки на сенсорных устройствах работают так же, как кнопки мыши, и в основном используются на сенсорных устройствах типа указатель или со стилусом.
Поддерживаются следующие кнопки:
BTN_LEFT: сопоставлено сMotionEvent.BUTTON_PRIMARY.BTN_RIGHT: сопоставлено сMotionEvent.BUTTON_SECONDARY.BTN_MIDDLE: сопоставлено сMotionEvent.BUTTON_MIDDLE.BTN_BACKиBTN_SIDE– сопоставлены сMotionEvent.BUTTON_BACK. Нажатие этой кнопки также имитирует нажатие клавиши с кодомKeyEvent.KEYCODE_BACK.BTN_FORWARDиBTN_EXTRA: сопоставляются сMotionEvent.BUTTON_FORWARD. При нажатии этой кнопки также синтезируется нажатие клавиши с кодомKeyEvent.KEYCODE_FORWARD.BTN_STYLUS: сопоставлено сMotionEvent.BUTTON_SECONDARY.BTN_STYLUS2: сопоставлено сMotionEvent.BUTTON_TERTIARY.
Инструменты и их типы
Инструмент – это палец, стилус или другое устройство, используемое для взаимодействия с сенсорным устройством. Некоторые сенсорные устройства могут различать разные типы инструментов.
В других разделах Android, например в API MotionEvent, инструмент часто называется указателем.
Поддерживаются следующие типы инструментов:
BTN_TOOL_FINGERиMT_TOOL_FINGER: сопоставлены сMotionEvent.TOOL_TYPE_FINGER.BTN_TOOL_PENиMT_TOOL_PEN: сопоставлены сMotionEvent.TOOL_TYPE_STYLUS.BTN_TOOL_RUBBER: сопоставлено сMotionEvent.TOOL_TYPE_ERASER.BTN_TOOL_BRUSH: сопоставлено сMotionEvent.TOOL_TYPE_STYLUS.BTN_TOOL_PENCIL: сопоставлено сMotionEvent.TOOL_TYPE_STYLUS.BTN_TOOL_AIRBRUSH: сопоставлено сMotionEvent.TOOL_TYPE_STYLUS.BTN_TOOL_MOUSE: сопоставлено сMotionEvent.TOOL_TYPE_MOUSE.BTN_TOOL_LENS: сопоставлено сMotionEvent.TOOL_TYPE_MOUSE.BTN_TOOL_DOUBLETAP,BTN_TOOL_TRIPLETAPиBTN_TOOL_QUADTAP: сопоставлены сMotionEvent.TOOL_TYPE_FINGER.
Инструменты, которые можно использовать, не касаясь экрана
Инструменты могут касаться сенсорного устройства или находиться в пределах его диапазона и парить над ним. Не все сенсорные устройства могут распознавать присутствие инструмента, парящего над сенсорным устройством. Те, которые это делают, например радиочастотные дигитайзеры стилусов, часто могут обнаруживать, когда инструмент находится в ограниченном диапазоне дигитайзера.
Компонент InputReader позволяет отличать инструменты, касающиеся экрана, от инструментов, которые находятся над ним. Аналогично, приложения по-разному получают информацию о касании и наведении.
Прикосновения к экрану передаются приложениям как события касания с помощью MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN и MotionEvent.ACTION_POINTER_UP.
Приложения получают информацию о наведении инструментов в виде общих событий движения с помощью MotionEvent.ACTION_HOVER_ENTER, MotionEvent.ACTION_HOVER_MOVE и MotionEvent.ACTION_HOVER_EXIT.
Требования к драйверу сенсорного устройства
- Драйверы сенсорных устройств должны регистрировать только оси и коды клавиш для поддерживаемых осей и кнопок. Регистрация неподдерживаемых осей или кодов клавиш может привести к тому, что алгоритм классификации устройств будет работать неправильно или система будет некорректно определять возможности устройства. Например, если устройство сообщает код клавиши
BTN_TOUCH, система предполагает, чтоBTN_TOUCHвсегда используется для определения того, касается ли инструмент экрана. ПоэтомуBTN_TOUCHне следует использовать, чтобы указать, что инструмент находится в диапазоне и наведен. - Устройства с поддержкой одного касания используют следующие события ввода Linux:
ABS_X: (ОБЯЗАТЕЛЬНО) Координата X инструмента.ABS_Y: (ОБЯЗАТЕЛЬНО) Координата Y инструмента.ABS_PRESSURE: (необязательно) Сообщает о физическом давлении, приложенном к кончику инструмента, или о силе сигнала при касании.ABS_TOOL_WIDTH: (необязательно) Сообщает о площади поперечного сечения или ширине точки касания или самого инструмента.ABS_DISTANCE: необязательный параметр, который сообщает о расстоянии между инструментом и поверхностью сенсорного устройства.ABS_TILT_X– необязательный параметр, который позволяет сообщить об угле наклона инструмента относительно поверхности сенсорного устройства по оси X.ABS_TILT_Y: (необязательно) сообщает о наклоне инструмента относительно поверхности сенсорного устройства по оси Y.BTN_TOUCH: (ОБЯЗАТЕЛЬНО) указывает, касается ли инструмент устройства.BTN_LEFT,BTN_RIGHT,BTN_MIDDLE,BTN_BACK,BTN_SIDE,BTN_FORWARD,BTN_EXTRA,BTN_STYLUS,BTN_STYLUS2: (необязательно) сообщает о состоянии кнопки.BTN_TOOL_FINGER,BTN_TOOL_PEN,BTN_TOOL_RUBBER,BTN_TOOL_BRUSH,BTN_TOOL_PENCIL,BTN_TOOL_AIRBRUSH,BTN_TOOL_MOUSE,BTN_TOOL_LENS,BTN_TOOL_DOUBLETAP,BTN_TOOL_TRIPLETAP,BTN_TOOL_QUADTAP: (необязательно) тип инструмента.
- Устройства с поддержкой мультисенсорного ввода используют следующие события ввода Linux:
ABS_MT_POSITION_X: (ОБЯЗАТЕЛЬНО) Координата X инструмента.ABS_MT_POSITION_Y: (ОБЯЗАТЕЛЬНО) Координата Y инструмента.ABS_MT_PRESSURE– необязательно. Сообщает о физическом давлении, приложенном к кончику инструмента, или о силе сигнала сенсорного контакта.ABS_MT_TOUCH_MAJOR: необязательный атрибут, который позволяет сообщить площадь поперечного сечения точки касания или длину более длинной стороны точки касания.ABS_MT_TOUCH_MINOR: (необязательно) сообщает о длине меньшей стороны области касания. Эту ось не следует использовать, еслиABS_MT_TOUCH_MAJORсообщает о площади.ABS_MT_WIDTH_MAJOR: (необязательно) площадь поперечного сечения инструмента или длина его большей стороны. Не используйте эту ось, если не знаете размеров инструмента.ABS_MT_WIDTH_MINOR(необязательно). Длина меньшей стороны инструмента. Эту ось не следует использовать, еслиABS_MT_WIDTH_MAJORсообщает о площади или если размеры самого инструмента неизвестны.ABS_MT_ORIENTATION(необязательно) – ориентация инструмента.ABS_MT_DISTANCE– (необязательно) расстояние от инструмента до поверхности сенсорного устройства.ABS_MT_TOOL_TYPE: (необязательно) сообщает тип инструмента какMT_TOOL_FINGERилиMT_TOOL_PEN.ABS_MT_TRACKING_ID: (необязательно) – идентификатор отслеживания инструмента. Идентификатор отслеживания – это произвольное неотрицательное целое число, которое используется для идентификации и отслеживания каждого инструмента независимо, когда активны несколько инструментов. Например, когда устройство касается нескольких пальцев, каждому пальцу должен быть назначен отдельный идентификатор отслеживания, который используется до тех пор, пока палец остается в контакте. Идентификаторы отслеживания можно использовать повторно, когда связанные с ними инструменты выходят из зоны действия.ABS_MT_SLOT: необязательный параметр, который позволяет сообщить идентификатор слота инструмента при использовании протокола Linux Multi-touch B. Подробную информацию можно найти в документации по протоколу мультитач для Linux.BTN_TOUCH: (ОБЯЗАТЕЛЬНО) Указывает, касается ли инструмент устройства.BTN_LEFT,BTN_RIGHT,BTN_MIDDLE,BTN_BACK,BTN_SIDE,BTN_FORWARD,BTN_EXTRA,BTN_STYLUS,BTN_STYLUS2: (необязательно) Сообщает о состоянии кнопки.BTN_TOOL_FINGER,BTN_TOOL_PEN,BTN_TOOL_RUBBER,BTN_TOOL_BRUSH,BTN_TOOL_PENCIL,BTN_TOOL_AIRBRUSH,BTN_TOOL_MOUSE,BTN_TOOL_LENS,BTN_TOOL_DOUBLETAP,BTN_TOOL_TRIPLETAP,BTN_TOOL_QUADTAP: (необязательно) – тип инструмента.
- Если определены оси для обоих протоколов, то используются только оси для мультисенсорного протокола, а оси для односенсорного игнорируются.
Минимальные и максимальные значения осей
ABS_X,ABS_Y,ABS_MT_POSITION_XиABS_MT_POSITION_Yопределяют границы активной области устройства в единицах поверхности, характерных для этого устройства. В случае с сенсорным экраном активная область – это часть сенсорного устройства, которая фактически покрывает дисплей.Для сенсорного экрана система автоматически интерполирует координаты касания, полученные в единицах поверхности, в координаты касания в пикселях экрана по следующей формуле:
displayX = (x - minX) * displayWidth / (maxX - minX + 1) displayY = (y - minY) * displayHeight / (maxY - minY + 1)Сенсорный экран может регистрировать прикосновения за пределами активной области.
Касания, инициированные за пределами активной области, не передаются приложениям, но могут использоваться для виртуальных клавиш.
Прикосновения, которые начинаются в активной области или входят в нее и выходят из нее, передаются приложениям. Поэтому, если касание начинается в пределах приложения, а затем перемещается за пределы активной области, приложение может получать события касания с отрицательными координатами экрана или за пределами экрана. Это ожидаемое поведение.
Сенсорное устройство не должно ограничивать координаты касания границами активной области. Если касание выходит за пределы активной области, оно должно быть зарегистрировано как находящееся за пределами активной области или не должно регистрироваться вообще.
Например, если палец пользователя касается сенсорного экрана в левом верхнем углу, может быть зарегистрирована координата (minX, minY). Если палец продолжает двигаться за пределы активной области, сенсорный экран должен либо начать передавать координаты с компонентами меньше minX и minY, например (minX - 2, minY - 3), либо вообще прекратить передавать данные о касании. Другими словами, сенсорный экран не должен сообщать (minX, minY), когда палец пользователя касается области за пределами активной зоны.
Ограничение координат касания краем экрана создает искусственную жесткую границу, которая мешает системе плавно отслеживать движения, выходящие за пределы области экрана или входящие в нее.
Значения, сообщаемые
ABS_PRESSUREилиABS_MT_PRESSURE, если они вообще сообщаются, должны быть ненулевыми, когда инструмент касается устройства, и нулевыми в противном случае, чтобы указать, что инструмент находится в режиме наведения.Указывать информацию о давлении необязательно, но мы настоятельно рекомендуем это делать. Приложения могут использовать информацию о давлении, чтобы реализовать рисование с учетом силы нажатия и другие эффекты.
Значения, сообщаемые
ABS_TOOL_WIDTH,ABS_MT_TOUCH_MAJOR,ABS_MT_TOUCH_MINOR,ABS_MT_WIDTH_MAJORилиABS_MT_WIDTH_MINOR, должны быть ненулевыми, когда инструмент касается устройства, и нулевыми в противном случае, но это не обязательно. Например, сенсорное устройство может определять размер касания пальцем, но не стилусом.Указывать информацию о размере необязательно, но настоятельно рекомендуется. Приложения могут использовать информацию о давлении для рисования с учетом силы нажатия и других эффектов.
Значения, полученные с помощью
ABS_DISTANCEилиABS_MT_DISTANCE, должны стремиться к нулю, когда инструмент касается устройства. Расстояние может быть ненулевым, даже если инструмент находится в прямом контакте. Точные значения зависят от того, как оборудование измеряет расстояние.Передача информации о расстоянии необязательна, но рекомендуется для устройств со стилусом.
Значения, полученные с помощью
ABS_TILT_XиABS_TILT_Y, должны быть равны нулю, когда инструмент перпендикулярен устройству. Ненулевой наклон означает, что инструмент удерживается под углом.Углы наклона по осям X и Y должны быть указаны в градусах от перпендикуляра. Центральная точка (перпендикулярная) определяется по формуле
(max + min) / 2для каждой оси. Значения меньше центральной точки указывают на увеличение угла обзора или наклон влево, а значения больше центральной точки – на уменьшение угла обзора или наклон вправо.Функция
InputReaderпреобразует компоненты наклона по осям X и Y в угол наклона, перпендикулярный плоскости, в диапазоне от 0 доPI / 2радиан, и угол ориентации в плоскости в диапазоне от-PIдоPIрадиан. Такое представление позволяет описать ориентацию так же, как и для касаний пальцами.Передавать данные о наклоне необязательно, но рекомендуется для устройств со стилусом.
Если тип инструмента указан в
ABS_MT_TOOL_TYPE, он имеет приоритет над информацией о типе инструмента, указанной вBTN_TOOL_*. Если информация о типе инструмента отсутствует, по умолчанию используется значениеMotionEvent.TOOL_TYPE_FINGER.Инструмент считается активным, если выполняются следующие условия:
При использовании протокола Single-touch инструмент активен, если
BTN_TOUCHилиBTN_TOOL_*имеет значение 1.Это условие означает, что у
InputReaderдолжна быть хотя бы какая-то информация о характере инструмента, например о том, касается ли он экрана, или хотя бы о его типе. Если информация недоступна, инструмент считается неактивным (вне зоны действия).- При использовании протокола мультитач "А" инструмент активен, если он указан в последнем отчете о синхронизации. Когда инструмент перестанет появляться в отчетах о синхронизации, он будет удален.
- При использовании протокола мультитач B инструмент активен, пока у него есть активный слот. Когда ячейка очищается, инструмент перестает существовать.
- Инструмент считается наведенным, если выполняются следующие условия:
- Если инструмент
BTN_TOOL_MOUSEилиBTN_TOOL_LENS, то он не находится в режиме наведения, даже если выполняется одно из следующих условий: - Если инструмент активен и драйвер передает информацию о давлении, а давление равно нулю, то инструмент находится в режиме наведения.
- Если инструмент активен, драйвер поддерживает код клавиши
BTN_TOUCHи значениеBTN_TOUCHравно нулю, то инструмент находится в режиме наведения.
- Если инструмент
InputReaderподдерживает протоколы мультисенсорного ввода A и B. Новые драйверы должны использовать протокол B, но оба варианта работают.Начиная с Android 4.0, драйверы сенсорного экрана могут быть изменены, чтобы соответствовать спецификации протокола ввода Linux.
Возможно, вам потребуется сделать следующее:
Когда инструмент становится неактивным (палец убирается), он должен перестать появляться в последующих отчетах о синхронизации мультисенсорного ввода. Когда все инструменты становятся неактивными (все пальцы подняты), драйвер должен отправить пустой пакет отчета о синхронизации, например
SYN_MT_REPORT, за которым следуетSYN_REPORT.В предыдущих версиях Android события "up" регистрировались при отправке значения давления, равного 0. Старое поведение несовместимо со спецификацией протокола ввода Linux и больше не поддерживается.
Физическое давление или силу сигнала следует указывать с помощью параметра
ABS_MT_PRESSURE.В предыдущих версиях Android информация о давлении извлекалась из
ABS_MT_TOUCH_MAJOR. Предыдущее поведение было несовместимо со спецификацией протокола ввода Linux и больше не поддерживается.- Информацию о размере сенсорного экрана следует передавать с помощью
ABS_MT_TOUCH_MAJOR.В предыдущих версиях Android информация о размере извлекалась из
ABS_MT_TOOL_MAJOR. Предыдущее поведение было несовместимо со спецификацией протокола ввода Linux и больше не поддерживается.
Управление с помощью сенсорного устройства
Ниже приведена краткая информация о том, как работают сенсорные устройства на Android.
EventHubсчитывает необработанные события из драйвераevdev.InputReaderобрабатывает необработанные события и обновляет внутреннее состояние, связанное с положением и другими характеристиками каждого инструмента. а также отслеживает состояние кнопок.- Если была нажата или отпущена клавиша Назад или Вперед,
InputReaderуведомляетInputDispatcherо ключевом событии. InputReaderопределяет, было ли нажатие виртуальной клавиши. Если да, тоInputDispatcherполучает уведомление о ключевом событии.InputReaderопределяет, было ли касание инициировано в пределах экрана. Если это так, тоInputDispatcherполучает уведомление о событии касания.- Если нет инструментов, касающихся экрана, но есть хотя бы один инструмент, находящийся над ним,
InputReaderуведомляетInputDispatcherо событии наведения. - Если тип сенсорного устройства – указатель,
InputReaderвыполняет обнаружение жестов указателя, перемещает указатель и пятно в соответствии с жестами и уведомляетInputDispatcherо событии указателя. - Функция
InputDispatcherиспользуетWindowManagerPolicy, чтобы определить, нужно ли отправлять события и должны ли они выводить устройство из спящего режима. ЗатемInputDispatcherдоставляет события в нужные приложения.
Настройка сенсорного устройства
Поведение сенсорного устройства определяется его осями, кнопками, свойствами ввода, конфигурацией устройства ввода, виртуальной раскладкой клавиш и раскладкой клавиш.
Ниже приведена подробная информация о файлах, которые используются при настройке клавиатуры.
Свойства
Система использует множество свойств конфигурации устройства ввода, чтобы настроить и откалибровать поведение сенсорного устройства.
Одна из причин этого заключается в том, что драйверы сенсорных устройств часто сообщают характеристики касаний, используя единицы измерения, специфичные для устройства.
Например, многие сенсорные устройства измеряют площадь контакта с помощью внутренней шкалы, зависящей от устройства, например общего количества сенсорных узлов, которые были активированы при касании. Это необработанное значение размера не будет иметь значения для приложений, поскольку им необходимо знать физический размер и другие характеристики узлов датчиков сенсорного устройства.
Система использует параметры калибровки, закодированные в файлах конфигурации устройства ввода, чтобы декодировать, преобразовывать и нормализовать значения, сообщаемые сенсорным устройством, в более простое стандартное представление, понятное приложениям.
Соглашения в документации
В документации используются следующие обозначения для описания значений, которые система использует в процессе калибровки.
Необработанные значения осей
Следующие выражения обозначают необработанные значения, которые драйвер сенсорного устройства передает в виде событий EV_ABS.
raw.x- Значение оси
ABS_XилиABS_MT_POSITION_X. raw.y- Значение оси
ABS_YилиABS_MT_POSITION_Y. raw.pressure- Значение оси
ABS_PRESSUREилиABS_MT_PRESSURE, или 0, если оно недоступно. raw.touchMajor- Значение оси
ABS_MT_TOUCH_MAJORили 0, если оно недоступно. raw.touchMinor- Значение оси
ABS_MT_TOUCH_MINORилиraw.touchMajor, если оно недоступно. raw.toolMajor- Значение оси
ABS_TOOL_WIDTHилиABS_MT_WIDTH_MAJOR, или 0, если оно недоступно. raw.toolMinor- Значение оси
ABS_MT_WIDTH_MINORилиraw.toolMajor, если оно недоступно. raw.orientation- Значение оси
ABS_MT_ORIENTATIONили 0, если оно недоступно. raw.distance- Значение оси
ABS_DISTANCEилиABS_MT_DISTANCEили 0, если значение недоступно. raw.tiltX- Значение оси
ABS_TILT_Xили 0, если оно недоступно. raw.tiltY- Значение оси
ABS_TILT_Yили 0, если оно недоступно.
Диапазоны необработанных значений осей
Ниже приведены выражения, обозначающие границы необработанных значений. Они получаются путем вызова EVIOCGABS ioctl для каждой оси.
raw.*.min- Минимальное значение исходной оси (включительно).
raw.*.max- Максимальное значение исходной оси (включительно).
raw.*.range- Эквивалентно
raw.*.max - raw.*.min. raw.*.fuzz- Точность необработанной оси. Например, fuzz = 1 означает, что значения точны до +/- 1 единицы.
raw.width- Ширина области прикосновения, эквивалентная
raw.x.range + 1. raw.height- Высота области нажатия, эквивалентная
raw.y.range + 1.
Диапазоны выходных данных
Ниже приведены выражения, обозначающие характеристики выходной системы координат. Система использует линейную интерполяцию для преобразования информации о положении касания из единиц поверхности, используемых сенсорным устройством, в выходные единицы, которые передаются приложениям, например пиксели дисплея.
output.width- Ширина выходного изображения. Для сенсорных экранов (связанных с дисплеем) это ширина дисплея в пикселях. Для сенсорных панелей, не связанных с экраном, ширина вывода равна
raw.width, что указывает на отсутствие интерполяции. output.height- Высота выходного изображения. Для сенсорных экранов (связанных с дисплеем) это высота дисплея в пикселях. Для сенсорных панелей (не связанных с дисплеем) выходная высота равна
raw.height, что означает отсутствие интерполяции. output.diag- Длина диагонали выходной системы координат, эквивалентная
sqrt(output.width ^2 + output.height ^2).
Базовая конфигурация
Сопоставитель сенсорного ввода использует множество свойств конфигурации в файле конфигурации устройства ввода, чтобы задать значения калибровки. В таблице ниже описаны некоторые свойства конфигурации общего назначения. Остальные свойства описаны в следующих разделах вместе с полями, которые они помогают калибровать.
touch.deviceType
Определение: touch.deviceType = touchScreen |
touchPad | pointer | default
Указывает тип сенсорного устройства.
-
Если значение равно
touchScreen, сенсорное устройство является сенсорным экраном, связанным с дисплеем. -
Если значение равно
touchPad, сенсорное устройство является сенсорной панелью, не связанной с дисплеем. -
Если значение равно
pointer, сенсорное устройство представляет собой сенсорную панель, не связанную с дисплеем, и ее движения используются для косвенных многоточечных жестов указателя. -
Если указано значение
default, система автоматически определяет тип устройства в соответствии с алгоритмом классификации.
Подробнее о том, как тип устройства влияет на поведение сенсорного устройства, рассказывается в разделе Классификация.
В Android 3 и более ранних версиях все сенсорные устройства считались сенсорными экранами.
touch.orientationAware
Определение: touch.orientationAware = 0 | 1
Это правило определяет, должно ли сенсорное устройство реагировать на изменение ориентации экрана.
-
Если задано значение
1, координаты касаний, передаваемые сенсорным устройством, поворачиваются при изменении ориентации экрана. -
Если задано значение
0, координаты касаний, передаваемые сенсорным устройством, не зависят от изменений ориентации экрана.
Если устройство оснащено сенсорным экраном, по умолчанию используется значение 1, в противном случае – 0.
Система различает внутренние и внешние сенсорные экраны и дисплеи. Внутренний сенсорный экран с поддержкой ориентации поворачивается в зависимости от ориентации внутреннего дисплея. Внешний сенсорный экран с поддержкой ориентации поворачивается в зависимости от ориентации внешнего дисплея.
Ориентация используется для поддержки поворота сенсорных экранов на таких устройствах, как Nexus One. Например, если устройство повернуто на 90 градусов по часовой стрелке, абсолютные координаты касаний переназначаются таким образом, что касание в левом верхнем углу абсолютной системы координат сенсорного экрана регистрируется как касание в левом верхнем углу повернутой системы координат дисплея. Это делается для того, чтобы касания регистрировались в той же системе координат, которую приложения используют для отрисовки визуальных элементов.
До версии Honeycomb предполагалось, что все сенсорные устройства поддерживают ориентацию.
touch.gestureMode
Определение: touch.gestureMode = pointer | spots |
default
Указывает режим презентации для жестов указателя. Это свойство конфигурации имеет значение, только если сенсорное устройство относится к типу pointer.
-
Если выбрано значение
pointer, жесты на сенсорной панели будут отображаться с помощью курсора, похожего на указатель мыши. -
Если выбрано значение
spots, жесты на сенсорной панели будут представлены якорем, который соответствует центроиду жеста, и набором круглых точек, которые соответствуют положению отдельных пальцев.
Значение по умолчанию – pointer, если задано свойство INPUT_PROP_SEMI_MT, и spots в противном случае.
Поля X и Y
Поля X и Y содержат информацию о положении центра области касания.
Вычисления
Расчет выполняется просто: информация о положении от драйвера сенсорного экрана линейно интерполируется в выходную систему координат.
xScale = output.width / raw.width
yScale = output.height / raw.height
If not orientation aware or screen rotation is 0 degrees:
output.x = (raw.x - raw.x.min) * xScale
output.y = (raw.y - raw.y.min) * yScale
Else If rotation is 90 degrees:
output.x = (raw.y - raw.y.min) * yScale
output.y = (raw.x.max - raw.x) * xScale
Else If rotation is 180 degrees:
output.x = (raw.x.max - raw.x) * xScale
output.y = (raw.y.max - raw.y) * yScale
Else If rotation is 270 degrees:
output.x = (raw.y.max - raw.y) * yScale
output.y = (raw.x - raw.x.min) * xScale
End If
touchMajor, touchMinor, toolMajor, toolMinor, size fields
Поля touchMajor и touchMinor описывают приблизительные размеры области контакта в выходных единицах (пикселях).
Поля toolMajor и toolMinor описывают приблизительные размеры самого инструмента в выходных единицах (пикселях).
Поле size описывает нормализованный размер касания относительно самого большого возможного касания, которое может распознать сенсорное устройство. Минимальное возможное нормализованное значение – 0,0 (контакта нет или его невозможно измерить), а максимальное – 1,0 (область датчика заполнена).
Если можно измерить и длину, и ширину, то в поле touchMajor указывается более длинная сторона, а в поле touchMinor – более короткая. Если можно измерить только приблизительный диаметр контактной области, то значения полей touchMajor и touchMinor будут равны.
Аналогично, поле toolMajor указывает на большую сторону, а поле toolMinor – на меньшую сторону площади поперечного сечения инструмента.
Если размер касания недоступен, но доступен размер инструмента, то размер инструмента устанавливается равным размеру касания. Если размер инструмента недоступен, но доступен размер касания, то размер касания устанавливается равным размеру инструмента.
Сенсорные устройства измеряют и передают размер касания и инструмента по-разному. В текущей реализации поддерживаются три типа измерений: диаметр, площадь и геометрическая граничная рамка в единицах поверхности.
Определение: touch.size.calibration = none |
geometric | diameter
| area | default
Указывает, какие единицы измерения используются драйвером сенсорного экрана для передачи данных о размере касания и инструмента.
-
Если выбрано
none, размер будет равен нулю. -
Если указано значение
geometric, размер считается заданным в тех же единицах, что и позиция, поэтому он масштабируется аналогичным образом. -
Если указано значение
diameter, размер считается пропорциональным диаметру (ширине) касания или инструмента. -
Если значение равно
area, размер считается пропорциональным площади касания или инструмента. -
Если значение –
default, система использует калибровкуgeometric, если доступна осьraw.touchMajorилиraw.toolMajor, в противном случае используется калибровкаnone.
touch.size.scale
Определение: touch.size.scale = <неотрицательное число с плавающей запятой>
Указывает постоянный коэффициент масштабирования, используемый при калибровке.
Значение по умолчанию: 1.0 .
touch.size.bias
Определение: touch.size.bias = <неотрицательное число с плавающей запятой>
Указывает постоянное значение смещения, используемое при калибровке.
Значение по умолчанию: 0.0 .
touch.size.isSummed
Определение: touch.size.isSummed = 0 | 1
Указывает, сообщается ли размер как сумма размеров всех активных контактов или сообщается индивидуально для каждого контакта.
-
Если значение равно
1, то перед использованием указанный размер делится на количество контактов. -
Если задано значение
0, то размер используется без изменений.
Значение по умолчанию: 0 .
Некоторые сенсорные устройства, особенно устройства Semi-MT, не могут различать отдельные размеры нескольких касаний, поэтому они сообщают размер, представляющий общую площадь или ширину. Для таких устройств это свойство должно иметь значение 1. Если вы не уверены, какое значение выбрать, укажите 0.
Вычисления
Расчет полей touchMajor, touchMinor, toolMajor, toolMinor и size зависит от заданных параметров калибровки.
If raw.touchMajor and raw.toolMajor are available:
touchMajor = raw.touchMajor
touchMinor = raw.touchMinor
toolMajor = raw.toolMajor
toolMinor = raw.toolMinor
Else If raw.touchMajor is available:
toolMajor = touchMajor = raw.touchMajor
toolMinor = touchMinor = raw.touchMinor
Else If raw.toolMajor is available:
touchMajor = toolMajor = raw.toolMajor
touchMinor = toolMinor = raw.toolMinor
Else
touchMajor = toolMajor = 0
touchMinor = toolMinor = 0
size = 0
End If
size = avg(touchMajor, touchMinor)
If touch.size.isSummed == 1:
touchMajor = touchMajor / numberOfActiveContacts
touchMinor = touchMinor / numberOfActiveContacts
toolMajor = toolMajor / numberOfActiveContacts
toolMinor = toolMinor / numberOfActiveContacts
size = size / numberOfActiveContacts
End If
If touch.size.calibration == "none":
touchMajor = toolMajor = 0
touchMinor = toolMinor = 0
size = 0
Else If touch.size.calibration == "geometric":
outputScale = average(output.width / raw.width, output.height / raw.height)
touchMajor = touchMajor * outputScale
touchMinor = touchMinor * outputScale
toolMajor = toolMajor * outputScale
toolMinor = toolMinor * outputScale
Else If touch.size.calibration == "area":
touchMajor = sqrt(touchMajor)
touchMinor = touchMajor
toolMajor = sqrt(toolMajor)
toolMinor = toolMajor
Else If touch.size.calibration == "diameter":
touchMinor = touchMajor
toolMinor = toolMajor
End If
If touchMajor != 0:
output.touchMajor = touchMajor * touch.size.scale + touch.size.bias
Else
output.touchMajor = 0
End If
If touchMinor != 0:
output.touchMinor = touchMinor * touch.size.scale + touch.size.bias
Else
output.touchMinor = 0
End If
If toolMajor != 0:
output.toolMajor = toolMajor * touch.size.scale + touch.size.bias
Else
output.toolMajor = 0
End If
If toolMinor != 0:
output.toolMinor = toolMinor * touch.size.scale + touch.size.bias
Else
output.toolMinor = 0
End If
output.size = size
поле давления
Поле pressure описывает приблизительное физическое давление, приложенное к сенсорному устройству, в виде нормализованного значения от 0,0 (нет касания) до 1,0 (нормальное давление).
Нулевое давление означает, что инструмент находится в воздухе.
touch.pressure.calibration
Определение: touch.pressure.calibration = none |
physical | amplitude | default
Указывает тип измерения, используемый драйвером сенсорного экрана для передачи данных о силе нажатия.
-
Если значение равно
none, давление неизвестно, поэтому при касании оно устанавливается на 1,0, а при наведении – на 0,0. -
Если выбрано значение
physical, предполагается, что ось давления измеряет фактическую физическую интенсивность давления, приложенного к сенсорной панели. -
Если указано значение
amplitude, ось давления используется для измерения амплитуды сигнала, которая связана с размером контакта и приложенным давлением. -
Если значение –
default, система использует калибровкуphysical, если доступна ось давления, илиnone.
touch.pressure.scale
Определение: touch.pressure.scale = <неотрицательное число с плавающей запятой>
Указывает постоянный коэффициент масштабирования, используемый при калибровке.
Значение по умолчанию: 1.0 / raw.pressure.max .
Вычисления
Расчет значения поля pressure зависит от указанных параметров калибровки.
If touch.pressure.calibration == "physical" or "amplitude":
output.pressure = raw.pressure * touch.pressure.scale
Else
If hovering:
output.pressure = 0
Else
output.pressure = 1
End If
End If
поля ориентации и наклона;
Поле orientation описывает ориентацию касания и инструмента в виде углового измерения. Ориентация 0 означает, что главная ось ориентирована вертикально, -PI/2 – что главная ось ориентирована влево, а PI/2 – что главная ось ориентирована вправо. Если стилус присутствует, диапазон ориентации может быть описан в виде полного круга от -PI или PI.
Поле tilt описывает наклон инструмента в виде углового измерения.
Наклон 0 означает, что инструмент перпендикулярен поверхности.
Наклон PI/2 означает, что инструмент лежит на поверхности ровно.
touch.orientation.calibration
Определение: touch.orientation.calibration = none |
interpolated | vector | default
Указывает тип измерения, используемый драйвером сенсорного экрана для определения ориентации.
- Если указано значение
none, ориентация неизвестна, поэтому задано значение 0. - Если значение равно
interpolated, ориентация линейно интерполируется таким образом, что необработанное значениеraw.orientation.minсопоставляется с-PI/2, а необработанное значениеraw.orientation.max– сPI/2. Центральное значение(raw.orientation.min + raw.orientation.max) / 2сопоставляется с0. - Если значение равно
vector, ориентация интерпретируется как упакованный вектор, состоящий из двух 4-битных полей со знаком. Такое представление используется в устройствах Atmel Object Based Protocol. После декодирования вектор дает угол ориентации и величину достоверности. Величина достоверности используется для масштабирования информации о размере, если она не является геометрической. - Если значение равно
default, система использует калибровкуinterpolated, если доступна ось ориентации, в противном случае –none.
Вычисления
Расчет полей orientation и tilt зависит от заданных параметров калибровки и доступных входных данных.
If touch.tiltX and touch.tiltY are available:
tiltXCenter = average(raw.tiltX.min, raw.tiltX.max)
tiltYCenter = average(raw.tiltY.min, raw.tiltY.max)
tiltXAngle = (raw.tiltX - tiltXCenter) * PI / 180
tiltYAngle = (raw.tiltY - tiltYCenter) * PI / 180
output.orientation = atan2(-sin(tiltXAngle), sinf(tiltYAngle))
output.tilt = acos(cos(tiltXAngle) * cos(tiltYAngle))
Else If touch.orientation.calibration == "interpolated":
center = average(raw.orientation.min, raw.orientation.max)
output.orientation = PI / (raw.orientation.max - raw.orientation.min)
output.tilt = 0
Else If touch.orientation.calibration == "vector":
c1 = (raw.orientation & 0xF0) >> 4
c2 = raw.orientation & 0x0F
If c1 != 0 or c2 != 0:
If c1 >= 8 Then c1 = c1 - 16
If c2 >= 8 Then c2 = c2 - 16
angle = atan2(c1, c2) / 2
confidence = sqrt(c1*c1 + c2*c2)
output.orientation = angle
If touch.size.calibration == "diameter" or "area":
scale = 1.0 + confidence / 16
output.touchMajor *= scale
output.touchMinor /= scale
output.toolMajor *= scale
output.toolMinor /= scale
End If
Else
output.orientation = 0
End If
output.tilt = 0
Else
output.orientation = 0
output.tilt = 0
End If
If orientation aware:
If screen rotation is 90 degrees:
output.orientation = output.orientation - PI / 2
Else If screen rotation is 270 degrees:
output.orientation = output.orientation + PI / 2
End If
End If
поле "Расстояние"
Поле distance описывает расстояние между инструментом и поверхностью сенсорного устройства. Значение 0,0 указывает на прямой контакт, а более высокие значения – на увеличивающееся расстояние от поверхности.
touch.distance.calibration
Определение: touch.distance.calibration = none |
scaled | default
Указывает тип измерения, используемый драйвером сенсорного экрана для передачи данных о расстоянии.
-
Если значение равно
none, расстояние неизвестно, поэтому оно устанавливается равным 0. -
Если значение равно
scaled, сообщаемое расстояние умножается на постоянный коэффициент масштабирования. -
Если задано значение
default, система использует калибровкуscaled, если доступна ось расстояния, илиnone.
touch.distance.scale
Определение: touch.distance.scale = <неотрицательное число с плавающей запятой>
Указывает постоянный коэффициент масштабирования, используемый при калибровке.
Значение по умолчанию: 1.0 .
Вычисления
Расчет поля distance зависит от указанных параметров калибровки.
If touch.distance.calibration == "scaled":
output.distance = raw.distance * touch.distance.scale
Else
output.distance = 0
End If
Пример
# Input device configuration file for a touch screen that supports pressure, # size and orientation. The pressure and size scale factors were obtained # by measuring the characteristics of the device itself and deriving # useful approximations based on the resolution of the touch sensor and the # display. # # Note that these parameters are specific to a particular device model. # Different parameters need to be used for other devices. # Basic Parameters touch.deviceType = touchScreen touch.orientationAware = 1 # Size # Based on empirical measurements, we estimate the size of the contact # using size = sqrt(area) * 28 + 0. touch.size.calibration = area touch.size.scale = 28 touch.size.bias = 0 touch.size.isSummed = 0 # Pressure # Driver reports signal strength as pressure. # # A normal index finger touch typically registers about 80 signal strength # units although we don't expect these values to be accurate. touch.pressure.calibration = amplitude touch.pressure.scale = 0.0125 # Orientation touch.orientation.calibration = vector
Примечания о совместимости
Свойства конфигурации для сенсорных устройств значительно изменились в Android 4.0 (Ice Cream Sandwich). Все файлы конфигурации устройств ввода для сенсорных устройств должны быть обновлены, чтобы использовать новые свойства конфигурации.
Возможно, вам также потребуется обновить драйверы сенсорного экрана.
Файлы сопоставления виртуальных клавиш
На сенсорных устройствах можно использовать виртуальные клавиши.
Это можно сделать несколькими способами в зависимости от возможностей сенсорного контроллера. Некоторые контроллеры сенсорного экрана можно настроить на реализацию программных клавиш, задав регистры встроенного ПО. В других случаях сопоставление координат касания с кодами клавиш лучше выполнять программно.
Если виртуальные клавиши реализованы в программном обеспечении, ядро должно экспортировать файл сопоставления виртуальных клавиш virtualkeys.<devicename> в качестве свойства платы. Например, если драйвер сенсорного экрана сообщает, что его название – "touchyfeely", то файл виртуальной карты клавиш должен иметь путь /sys/board_properties/virtualkeys.touchyfeely.
Файл раскладки виртуальных клавиш описывает координаты и коды Linux виртуальных клавиш на сенсорном экране.
Помимо файла раскладки виртуальных клавиш, должен быть соответствующий файл раскладки клавиш и файл раскладки символов клавиш, чтобы сопоставить коды клавиш Linux с кодами клавиш Android и указать тип клавиатуры (обычно SPECIAL_FUNCTION).
Синтаксис
Файл виртуальной раскладки клавиатуры – это обычный текстовый файл, состоящий из последовательности описаний раскладки виртуальных клавиш, разделенных символами новой строки или двоеточиями.
Строки комментариев начинаются с символа # и продолжаются до конца строки.
Каждый виртуальный ключ состоит из шести компонентов, разделенных двоеточиями:
0x01– код версии. Всегда должен иметь значение0x01.- <Linux key code> – код виртуальной клавиши в Linux.
- <centerX>: координата X центра виртуальной клавиши в пикселях.
- <centerY> – координата Y центра виртуальной клавиши в пикселях.
- <width> – ширина виртуальной клавиши в пикселях.
- <height> – высота виртуальной клавиши в пикселях.
Все координаты и размеры указываются в системе координат экрана.
Ниже приведен файл виртуальной карты клавиш, записанный в одну строку.
# All on one line 0x01:158:55:835:90:55:0x01:139:172:835:125:55:0x01:102:298:835:115:55:0x01:217:412:835:95:55
Один и тот же файл сопоставления виртуальных клавиш можно записать в несколько строк.
# One key per line 0x01:158:55:835:90:55 0x01:139:172:835:125:55 0x01:102:298:835:115:55 0x01:217:412:835:95:55
В примере выше разрешение сенсорного экрана составляет 480 x 800. Таким образом, все виртуальные клавиши имеют координату <centerY> 835, которая находится немного ниже видимой области сенсорного экрана.
Первый ключ имеет код сканирования Linux 158 (KEY_BACK), centerX 55, centerY 835, width 90 и height 55.
Пример
Файл раскладки виртуальной клавиатуры: /sys/board_properties/virtualkeys.touchyfeely.
0x01:158:55:835:90:55 0x01:139:172:835:125:55 0x01:102:298:835:115:55 0x01:217:412:835:95:55
Файл раскладки клавиатуры: /system/usr/keylayout/touchyfeely.kl.
key 158 BACK key 139 MENU key 172 HOME key 217 SEARCH
Файл сопоставления клавиш: /system/usr/keychars/touchyfeely.kcm.
type SPECIAL_FUNCTION
Косвенные жесты указателя с несколькими касаниями
В режиме указателя система распознает следующие жесты:
- Нажатие одним пальцем – клик.
- Переместите указатель одним пальцем.
- Перетаскивание указателя: перемещение одним пальцем и нажатие кнопок.
- Движение двумя пальцами в одном направлении: перетаскивание области под указателем в этом направлении. Указатель при этом не перемещается.
- Движение двумя пальцами, когда они сдвигаются или раздвигаются в разных направлениях: панорамирование, масштабирование или поворот области вокруг указателя. Сам указатель при этом не перемещается.
- Движение несколькими пальцами: произвольный жест.
Распознавание касаний ладони
Начиная с Android 13 система может автоматически отклонять ввод с ладоней, когда включена встроенная платформа. Собственные решения по-прежнему поддерживаются, но их может потребоваться изменить, чтобы они возвращали флаг TOOL_TYPE_PALM при обнаружении ладони. Встроенный фреймворк также работает в сочетании с пользовательскими решениями.
Модель анализирует первые 90 мс данных о жесте, текущий указатель и окружающие указатели, а затем определяет, насколько далеко от края экрана находятся касания.
Затем он определяет, какие из указателей являются ладонями. Также учитывается размер каждого контакта, возвращаемый методами touchMajor и touchMinor. После этого фреймворк Android удаляет из потока касаний указатели, отмеченные как ладони.
Если указатель уже был отправлен приложениям, система выполняет одно из следующих действий:
- Если есть другие активные указатели, отменяет указатель с заданными значениями
ACTION_POINTER_UPиFLAG_CANCELED. - Если это единственный указатель, он отменяется с помощью
ACTION_CANCEL.
Публичный API MotionEvent.FLAG_CANCELED указывает, что текущее событие не должно вызывать действия пользователя. Этот флаг устанавливается и для ACTION_CANCEL, и для ACTION_POINTER_UP.
Если указатель ладони не был отправлен в приложения, система просто отбрасывает его.
Как включить функцию защиты от случайных касаний
- В драйвере сенсорного экрана используйте макрос
input_abs_set_res, чтобы задать разрешение для следующих полей (единицы измерения – пиксели на мм):ABS_MT_POSITION_XABS_MT_POSITION_YABS_MT_TOUCH_MAJORABS_MT_TOUCH_MINOR
Поддержка
ABS_MT_TOUCH_MINORнеобязательна. Если же устройство поддерживает 4K, убедитесь, что разрешение установлено правильно. - Чтобы убедиться, что поля заданы правильно, выполните следующую команду:
$ adb shell getevent -li - Чтобы включить функцию во время выполнения, запустите:
$ adb shell device_config put input_native_boot palm_rejection_enabled 1 - Перезапустите процесс
system_server.$ adb shell stop && adb shell start - Убедитесь, что в
adb shell dumpsys inputуказано, что внутриUnwantedInteractionBlockerесть функция распознавания касаний ладонью. Если этого не происходит, проверьте журналы, связанные с вводом, чтобы найти подсказки о том, что может быть неправильно настроено.Пример:
UnwantedInteractionBlocker: mEnablePalmRejection: true isPalmRejectionEnabled (flag value): true mPalmRejectors: deviceId = 3: mDeviceInfo: max_x =max_y = x_res = 11.00 y_res = 11.00 major_radius_res = 1.00 minor_radius_res = 1.00 minor_radius_supported = true touch_major_res = 1 touch_minor_res = 1 mSlotState: mSlotsByPointerId: mPointerIdsBySlot: mSuppressedPointerIds: {} - Чтобы включить функцию навсегда, добавьте соответствующую команду sysprop в файл
init**rc:setprop persist.device_config.input_native_boot.palm_rejection_enabled 1