Совместимость ввода на больших экранах

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

  • Проверьте основные функции клавиатуры, например 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) для определенного кода клавиши. Чтобы проверить, используется ли определенная клавиша-модификатор, введите:

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 обрабатывают стилус как ввод с сенсорного экрана. К некоторым устройствам также можно подключить графический планшет через USB или Bluetooth, например Wacom Intuos. Приложения Android могут получать данные через Bluetooth, но не через USB.

Событие стилуса регистрируется как событие сенсорного экрана с помощью View#onTouchEvent() или View#onGenericMotionEvent() и содержит MotionEvent#getSource() типа SOURCE_STYLUS.

Объект MotionEvent содержит информацию о событии:

Исторические данные

Android объединяет входные события в пакеты и доставляет их один раз за кадр. Стилус может передавать данные о событиях с гораздо большей частотой, чем дисплей. При создании приложений для рисования проверяйте события, которые могли произойти недавно, с помощью следующих API getHistorical:

Распознавание касаний ладони

Когда пользователи рисуют, пишут или взаимодействуют с вашим приложением с помощью стилуса, они иногда касаются экрана ладонью. Событие касания (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:

  1. Как переключиться в режим разработчика и сделать устройство доступным для записи
  2. Нажмите Ctrl+Alt+F2, чтобы открыть терминал.
  3. Выполните команду sudo vi /etc/chrome_dev.conf.
  4. Нажмите i, чтобы изменить и добавить --ash-enable-palette в новую строку в конце файла.
  5. Чтобы сохранить изменения, нажмите Esc, а затем введите :, w, q и нажмите Ввод.
  6. Нажмите Ctrl + Alt + F1, чтобы вернуться к обычному интерфейсу ChromeOS.
  7. Выйдите из аккаунта и войдите снова

На панели должна появиться кнопка меню стилуса:

  • Нажмите кнопку стилуса на панели и выберите Новая заметка. Откроется пустая заметка к чертежу.
  • Сделайте скриншот. На панели выберите кнопку стилуса > Сделать снимок экрана или скачайте изображение. В уведомлении должна быть кнопка Добавить аннотацию к изображению. Приложение должно запуститься, а изображение – быть готовым к аннотированию.

Поддержка мыши и сенсорной панели

Большинству приложений нужно обрабатывать только три события, связанные с большими экранами: нажатие правой кнопки мыши, наведение указателя и перетаскивание.

Нажатие правой кнопки мыши

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

Чтобы обрабатывать события нажатия правой кнопки мыши, приложения должны зарегистрировать 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.

Расширенная поддержка указателя

Приложения, которые выполняют расширенную обработку ввода с помощью мыши и сенсорной панели, должны реализовать модификатор pointerInput, чтобы получить PointerEvent: 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" />

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