На устройствах с большим экраном пользователи часто взаимодействуют с приложениями с помощью клавиатуры, мыши, сенсорной панели, стилуса или геймпада. Чтобы приложение могло принимать входные данные от внешних устройств, сделайте следующее:
- Проверьте поддержку основных сочетаний клавиш, таких как Ctrl + Z для отмены, Ctrl + C для копирования и Ctrl + S для сохранения. Список сочетаний клавиш по умолчанию приведен в статье Обработка действий с клавиатуры.
- Проверьте расширенную поддержку клавиатуры. Например, убедитесь, что в приложении можно перемещаться с помощью клавиш Tab и стрелок, подтверждать ввод текста клавишей Ввод, а также запускать и приостанавливать воспроизведение в мультимедийных приложениях клавишей Пробел.
- Протестируйте базовые действия с помощью мыши, включая нажатие правой кнопки мыши для вызова контекстного меню, изменение значка при наведении указателя и прокрутку с помощью колеса мыши или сенсорной панели в пользовательских компонентах.
- Протестируйте устройства ввода, предназначенные для определенных приложений, например стилус, игровые контроллеры и MIDI-контроллеры для музыкальных приложений.
- Добавьте поддержку расширенных способов ввода, чтобы выделить приложение среди других. Например, в приложениях для диджеев можно использовать сенсорную панель в качестве кроссфейдера, в играх – захват мыши, а для пользователей, предпочитающих клавиатуру, – быстрые клавиши.
Клавиатура
То, как приложение реагирует на ввод с клавиатуры, влияет на удобство его использования на больших экранах. Существует три типа ввода с клавиатуры: навигация, нажатие клавиш и сочетания клавиш.
Навигация
Навигация с помощью клавиатуры редко реализуется в приложениях, ориентированных на сенсорный экран, но пользователи ожидают ее, когда они используют приложение и держат руки на клавиатуре. Навигация с помощью клавиатуры может быть необходима на телефонах, планшетах, складных устройствах и компьютерах для пользователей с особыми потребностями.
Во многих приложениях навигация с помощью клавиш со стрелками и клавиши Tab обрабатывается автоматически фреймворком Android. Например, элемент Button по умолчанию может быть в фокусе, и навигация с помощью клавиатуры должна работать без дополнительного кода. Чтобы включить навигацию с помощью клавиатуры для представлений, которые по умолчанию не поддерживают фокус, пометьте их как поддерживающие фокус. Это можно сделать программно или в XML:
Kotlin
yourView.isFocusable = true
Java
yourView.setFocusable(true);
Вы также можете задать атрибут focusable в файле макета:
android:focusable="true"
Подробнее об управлении фокусом…
Когда фокус включен, фреймворк Android создает карту навигации для всех представлений, на которых можно фокусироваться, на основе их положения. Обычно это работает как ожидается, и дальнейшая разработка не требуется. Если сопоставление по умолчанию не подходит для приложения, его можно переопределить следующим образом:
Kotlin
// Arrow keys
yourView.nextFocusLeftId = R.id.view_to_left
yourView.nextFocusRightId = R.id.view_to_right
yourView.nextFocusTopId = R.id.view_above
yourView.nextFocusBottomId = R.id.view_below
// Tab key
yourView.nextFocusForwardId = R.id.next_view
Java
// Arrow keys
yourView.setNextFocusLeftId(R.id.view_to_left);
yourView.setNextFocusRightId(R.id.view_to_left);
yourView.setNextFocusTopId(R.id.view_to_left);
yourView.setNextFocusBottomId(R.id.view_to_left);
// Tab key
yourView.setNextFocusForwardId(R.id.next_view);
Проверьте, можно ли получить доступ ко всем элементам интерфейса приложения, используя только клавиатуру. Часто используемые элементы должны быть доступны без мыши или сенсорного ввода.
Помните, что поддержка клавиатуры может быть важна для пользователей с ограниченными возможностями.
Сочетания клавиш
Для ввода текста, который обрабатывается виртуальной клавиатурой (IME), например дляEditText, приложения должны работать на устройствах с большим экраном без дополнительной разработки. Если фреймворк не может предугадать нажатие клавиш, приложения должны обрабатывать его самостоятельно. Это особенно актуально для приложений
с настраиваемыми представлениями.
Например, в чат-приложениях клавиша Ввод используется для отправки сообщения, в мультимедийных приложениях Пробел запускает и останавливает воспроизведение, а в играх клавиши W, A, S и D управляют движением.
Большинство приложений переопределяют обратный вызов onKeyUp() и добавляют ожидаемое поведение для каждого полученного кода клавиши:
Kotlin
kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
return when (keyCode) {
KeyEvent.KEYCODE_ENTER -> {
sendChatMessage()
true
}
KeyEvent.KEYCODE_SPACE -> {
playOrPauseMedia()
true
}
else -> super.onKeyUp(keyCode, event)
}
}
Java
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
sendMessage();
return true;
} else if (KeyEvent.KEYCODE_SPACE){
playOrPauseMedia();
return true;
} else {
return super.onKeyUp(keyCode, event);
}
}
Событие onKeyUp происходит, когда клавиша отпускается. Использование обратного вызова позволяет приложениям не обрабатывать несколько событий onKeyDown, если клавиша удерживается или отпускается медленно. Игры и приложения, в которых нужно определять момент нажатия клавиши или удерживает ли пользователь клавишу, могут прослушивать событие onKeyDown и самостоятельно обрабатывать повторяющиеся события onKeyDown.
Подробнее о том, как обрабатывать действия клавиатуры…
Ярлыки
При использовании аппаратной клавиатуры ожидается поддержка стандартных сочетаний клавиш, включающих Ctrl, Alt, Shift и Meta. Если в приложении нет быстрых клавиш, пользователям может быть неудобно с ним работать. Продвинутые пользователи также оценят ярлыки для часто используемых задач в приложении. Ярлыки упрощают работу с приложением и выгодно отличают его от других.
Вот некоторые из них: Ctrl + S (сохранить), Ctrl + Z (отменить) и Ctrl + Shift + Z (повторить). Список сочетаний клавиш по умолчанию приведен в статье Обработка действий с клавиатуры.
Чтобы включить быстрые клавиши, реализуйте dispatchKeyShortcutEvent() для перехвата всех комбинаций клавиш (Alt, Ctrl, Shift и Meta) для заданного кода клавиши.
Чтобы проверить определенную клавишу-модификатор, используйте:
KeyEvent.isCtrlPressed()KeyEvent.isShiftPressed()KeyEvent.isAltPressed()KeyEvent.isMetaPressed()или
Kotlin
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean {
return when (event.keyCode) {
KeyEvent.KEYCODE_O -> {
openFile() // Ctrl+O, Shift+O, Alt+O
true
}
KeyEvent.KEYCODE_Z-> {
if (event.isCtrlPressed) {
if (event.isShiftPressed) {
redoLastAction() // Ctrl+Shift+Z pressed
true
} else {
undoLastAction() // Ctrl+Z pressed
true
}
}
}
else -> {
return super.dispatchKeyShortcutEvent(event)
}
}
}
Java
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_O) {
openFile(); // Ctrl+O, Shift+O, Alt+O
return true;
} else if(event.getKeyCode() == KeyEvent.KEYCODE_Z) {
if (event.isCtrlPressed()) {
if (event.isShiftPressed()) {
redoLastAction();
return true;
}
else {
undoLastAction();
return true;
}
}
}
return super.dispatchKeyShortcutEvent(event);
}
Если отделить код быстрого клавишного сочетания от обработки других нажатий клавиш (например, onKeyUp() и onKeyDown()), клавиши-модификаторы будут приниматься по умолчанию, и вам не придется вручную реализовывать проверку клавиш-модификаторов в каждом случае. Разрешение всех комбинаций клавиш-модификаторов также может быть более удобным для пользователей, привыкших к различным раскладкам клавиатуры и операционным системам.
Однако вы также можете реализовать ярлыки в onKeyUp(), проверяя KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed() или KeyEvent.isAltPressed(). Это может быть проще в обслуживании, если измененное поведение клавиши больше похоже на изменение поведения приложения, чем на сочетание клавиш. Например, в играх, где W означает "идти вперед", а Shift + W – "бежать вперед".
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
return when(keyCode) {
KeyEvent.KEYCODE_W-> {
if (event.isShiftPressed) {
if (event.isCtrlPressed) {
flyForward() // Ctrl+Shift+W pressed
true
} else {
runForward() // Shift+W pressed
true
}
} else {
walkForward() // W pressed
true
}
}
else -> super.onKeyUp(keyCode, event)
}
}
Java
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_W) {
if (event.isShiftPressed()) {
if (event.isCtrlPressed()) {
flyForward(); // Ctrl+Shift+W pressed
return true;
} else {
runForward(); // Shift+W pressed
return true;
}
} else {
walkForward();
return true;
}
}
return super.onKeyUp(keyCode, event);
}
Справочник по сочетаниям клавиш
Стилус
Многие устройства с большим экраном поставляются со стилусом. Приложения Android обрабатывают ввод стилусом как ввод на сенсорном экране. К некоторым устройствам можно подключить графический планшет, например Wacom Intuos, через USB или Bluetooth. Приложения Android могут получать входные данные по Bluetooth, но не по USB.
Событие стилуса регистрируется как событие сенсорного экрана с помощью View#onTouchEvent() или View#onGenericMotionEvent() и содержит MotionEvent#getSource() типа SOURCE_STYLUS.
Объект MotionEvent содержит информацию о событии:
MotionEvent#getToolType()возвращаетTOOL_TYPE_FINGER,TOOL_TYPE_STYLUSилиTOOL_TYPE_ERASERв зависимости от инструмента, который коснулся экрана.MotionEvent#getPressure()сообщает о физическом давлении, приложенном к стилусу (если поддерживается).MotionEvent#getAxisValue()сMotionEvent.AXIS_TILTиMotionEvent.AXIS_ORIENTATIONпредоставляют информацию о физическом наклоне и ориентации стилуса (если поддерживается).
Исторические места
Android объединяет события ввода в пакеты и доставляет их один раз за кадр. Стилус может сообщать о событиях с гораздо более высокой частотой, чем дисплей. При создании приложений для рисования проверяйте события, которые могли произойти в недавнем прошлом, с помощью API getHistorical:
MotionEvent#getHistoricalX()MotionEvent#getHistoricalY()MotionEvent#getHistoricalPressure()MotionEvent#getHistoricalAxisValue()
Игнорирование касаний ладонью
Когда пользователи рисуют, пишут или взаимодействуют с вашим приложением с помощью стилуса, они иногда
касаются экрана ладонью. Событие касания (ACTION_DOWN или ACTION_POINTER_DOWN) может быть передано в приложение до того, как система распознает и проигнорирует случайное касание ладонью.
Android отменяет события касания ладонью, отправляя MotionEvent. Если приложение получает ACTION_CANCEL, отмените жест. Если приложение получает ACTION_POINTER_UP, проверьте, задано ли значение FLAG_CANCELED. Если да, отмените жест.
Не проверяйте только FLAG_CANCELED. В Android 13 (уровень API 33) и более поздних версиях система устанавливает FLAG_CANCELED для событий ACTION_CANCEL, но не делает этого в более ранних версиях Android.
Android 12
В Android 12 (уровень API 32) и более ранних версиях игнорирование ладони возможно только для событий касания с одним указателем. Если касание ладонью – единственный указатель, система отменяет событие, устанавливая ACTION_CANCEL для объекта события движения. Если другие указатели опущены, система устанавливает ACTION_POINTER_UP, чего недостаточно для обнаружения отклонения ладони.
Android 13
На устройствах с Android 13 (уровень API 33) и более поздними версиями, если касание ладонью – единственный указатель, система отменяет событие, устанавливая ACTION_CANCEL и FLAG_CANCELED для объекта события движения. Если нажаты другие указатели, система устанавливает ACTION_POINTER_UP и FLAG_CANCELED.
Когда приложение получает событие движения с ACTION_POINTER_UP, проверьте FLAG_CANCELED, чтобы определить, указывает ли событие на отклонение ладони (или отмену другого события).
Приложения для заметок
В ChromeOS есть специальный интент, который показывает пользователям зарегистрированные приложения для заметок. Чтобы зарегистрировать приложение как приложение для заметок, добавьте в манифест приложения следующее:
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Когда приложение зарегистрировано в системе, пользователь может выбрать его в качестве приложения для заметок по умолчанию. При запросе новой заметки приложение должно создать пустую заметку, готовую к вводу стилусом. Когда пользователь хочет добавить аннотацию к изображению (например, скриншоту или скачанному изображению), приложение запускается с ClipData, содержащим один или несколько элементов с URI content://. Приложение должно создать заметку, в которой первое прикрепленное изображение используется в качестве фонового, и перейти в режим, в котором пользователь может рисовать на экране стилусом.
Как протестировать интенты для ведения заметок без стилуса
Чтобы проверить, правильно ли приложение реагирует на интенты для создания заметок без активного стилуса, используйте следующий метод для отображения параметров создания заметок в ChromeOS:
- Как перейти в режим разработчика и разрешить запись на устройство
- Нажмите Ctrl + Alt + F2, чтобы открыть терминал.
- Выполните команду
sudo vi /etc/chrome_dev.conf. - Нажмите
i, чтобы перейти в режим редактирования, и добавьте--ash-enable-paletteв новую строку в конце файла. - Чтобы сохранить изменения, нажмите Esc, введите :, w, q и нажмите Ввод.
- Нажмите Ctrl + Alt + F1, чтобы вернуться к обычному интерфейсу ChromeOS.
- Выйдите из аккаунта и войдите снова
На панели задач появится меню стилуса.
- Нажмите кнопку стилуса на панели и выберите Новая заметка. Откроется пустая заметка с рисунком.
- Сделайте скриншот. На панели быстрого запуска нажмите кнопку стилуса > Сделать скриншот или скачайте изображение. В уведомлении должен быть вариант Добавить аннотацию к изображению. Приложение должно запуститься с изображением, готовым к аннотированию.
Поддержка мыши и сенсорной панели
Большинству приложений обычно требуется обрабатывать только три события, связанные с большими экранами: нажатие правой кнопкой мыши, наведение указателя и перетаскивание.
Нажатие правой кнопки мыши
Любые действия, которые вызывают появление контекстного меню, например нажатие и удержание элемента списка, должны также реагировать на нажатие правой кнопкой мыши.
Чтобы обрабатывать события нажатия правой кнопки мыши, приложения должны зарегистрировать View.OnContextClickListener:
Kotlin
yourView.setOnContextClickListener {
showContextMenu()
true
}
Java
yourView.setOnContextClickListener(v -> {
showContextMenu();
return true;
});
Подробнее о том, как создать контекстное меню…
Наведите указатель
Вы можете сделать макеты приложений более совершенными и простыми в использовании, обрабатывая события наведения. Это особенно важно для специальных компонентов просмотр
Kotlin
// Change the icon to a "hand" pointer on hover.
// Highlight the view by changing the background.
yourView.setOnHoverListener { view, _ ->
addVisualHighlighting(true)
view.pointerIcon =
PointerIcon.getSystemIcon(view.context, PointerIcon.TYPE_HAND)
true // Listener consumes the event.
}
Java
// Change the icon to a "hand" pointer on hover.
// Highlight the view by changing the background.
yourView.setOnHoverListener((view, event) -> {
addVisualHighlighting(true);
view.setPointerIcon(
PointerIcon.getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND)
);
return true; // Listener consumes the event.
});
Вот два наиболее распространенных примера:
- Указание пользователям на то, является ли элемент интерактивным, например, можно ли на него нажать или отредактировать, путем изменения значка указателя мыши.
- Добавление визуальной обратной связи для элементов в большом списке или сетке при наведении указателя мыши на них.
Перетаскивание
В многооконной среде пользователи ожидают, что смогут перетаскивать элементы между приложениями. Это касается как компьютеров, так и планшетов, телефонов и складных устройств в режиме разделенного экрана.
Подумайте, будут ли пользователи перетаскивать объекты в ваше приложение. Например, в фоторедактор можно перетаскивать фотографии, в аудиоплеер – аудиофайлы, а в программу для рисования – изображения.
Чтобы добавить поддержку перетаскивания, ознакомьтесь со следующими материалами: Как включить перетаскивание Android на ChromeOS – реализация перетаскивания (запись в блоге)
Особые условия для ChromeOS
- Не забудьте запросить разрешение с помощью
requestDragAndDropPermissions(), чтобы получить доступ к объектам, перетащенным из других приложений. Чтобы объект можно было перетащить в другое приложение, у него должен быть флаг
View.DRAG_FLAG_GLOBAL.
Поддержка расширенных указателей
Приложения, которые выполняют расширенную обработку ввода с помощью мыши и сенсорной панели, должны реализовывать модификатор
View#onGenericMotionEvent() и используйте [MotionEvent.getSource()][], чтобы различать SOURCE_MOUSE и SOURCE_TOUCHSCREEN.
Изучите объект MotionEvent, чтобы реализовать нужное поведение:
- Движение генерирует
ACTION_HOVER_MOVEсобытий. - Кнопки генерируют события
ACTION_BUTTON_PRESSиACTION_BUTTON_RELEASE. Вы также можете проверить текущее состояние всех кнопок мыши и сенсорной панели с помощьюgetButtonState(). - Прокрутка колесиком мыши генерирует события
ACTION_SCROLL.
Игровые контроллеры
Некоторые устройства Android с большим экраном поддерживают до четырех игровых контроллеров. Используйте стандартные API Android для игровых контроллеров (см. статью Поддержка игровых контроллеров).
Кнопки игрового контроллера сопоставляются с общими значениями в соответствии с общим сопоставлением. Однако не все производители игровых контроллеров следуют одним и тем же соглашениям о сопоставлении. Вы можете сделать игру намного удобнее, если позволите пользователям выбирать разные популярные раскладки контроллера. Подробнее об обработке нажатий кнопок геймпада…
Режим перевода ввода
В ChromeOS по умолчанию включен режим перевода ввода. Для большинства приложений Android этот режим помогает работать так, как ожидается в среде рабочего стола. Например, автоматически включается прокрутка двумя пальцами на сенсорной панели и колесом мыши, а также сопоставление необработанных координат экрана с координатами окна. Как правило, разработчикам приложений не нужно реализовывать эти функции самостоятельно.
Если в приложении реализовано собственное поведение ввода, например определено специальное действие сведения двух пальцев на сенсорной панели, или если эти преобразования ввода не обеспечивают события ввода, ожидаемые приложением, вы можете отключить режим преобразования ввода, добавив следующий тег в манифест Android:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />