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

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

  • Проверьте базовую поддержку клавиатуры , такую ​​как навигация по клавиатуре с помощью клавиш Tab и клавиш со стрелками, подтверждение ввода текста с помощью клавиши Enter и воспроизведение/пауза с помощью клавиши пробела в мультимедийных приложениях.
  • Добавьте стандартные сочетания клавиш, где это применимо; например, Ctrl + Z для отмены и Ctrl + S для сохранения.
  • Проверьте основные взаимодействия с мышью, например, щелчок правой кнопкой мыши для вызова контекстного меню, изменение значков при наведении, а также события прокрутки колеса мыши или трекпада в пользовательских представлениях.
  • Тестируйте устройства ввода для конкретных приложений, такие как стилус для приложений для рисования, игровые контроллеры для игр и MIDI-контроллеры для музыкальных приложений.
  • Рассмотрите расширенную поддержку ввода , которая могла бы выделить приложение на настольных компьютерах; например, сенсорная панель в качестве кроссфейдера для диджейских приложений, захват мыши для игр и расширенные сочетания клавиш для пользователей, ориентированных на клавиатуру.

Клавиатура

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

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

Для многих приложений достаточно простых клавиш со стрелками и навигации по вкладкам, и они в основном автоматически обрабатываются платформой Android. Например, представление Button по умолчанию является фокусируемым, а навигация с помощью клавиатуры обычно должна работать без какого-либо дополнительного кода. Чтобы включить навигацию с помощью клавиатуры для представлений, которые по умолчанию не являются фокусируемыми, разработчикам следует пометить их как фокусируемые, что можно сделать программно или в XML, как показано ниже. Дополнительную информацию см. в разделе «Обработка фокуса» .

Котлин

yourView.isFocusable = true

Ява

yourView.setFocusable(true);

Альтернативно вы можете установить атрибут focusable в файле макета:

android:focusable="true"

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

Котлин

// 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

Ява

// 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() и добавляют ожидаемое поведение для каждого полученного кода ключа, как показано ниже:

Котлин

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)
    }
}

Ява

@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. Если приложение их не реализует, это может разочаровать пользователей. Опытные пользователи также оценят ярлыки для часто используемых задач приложения. Ярлыки упрощают использование приложения и отличают его от приложений, у которых нет ярлыков.

Некоторые распространенные сочетания клавиш включают Ctrl + S (сохранить), Ctrl + Z (отменить) и Ctrl + Shift + Z (повторить). Пример некоторых более сложных сочетаний клавиш см. в списке сочетаний клавиш VLC Media Player .

Ярлыки можно реализовать с помощью dispatchKeyShortcutEvent() . Это перехватывает все комбинации мета-клавиш (Alt, Ctrl и Shift) для данного кода клавиши. Чтобы проверить определенный мета-ключ, используйте KeyEvent.isCtrlPressed() , KeyEvent.isShiftPressed() , KeyEvent.isAltPressed() или KeyEvent.hasModifiers() .

Отделение кода быстрого доступа от другой обработки нажатия клавиш (например, onKeyUp() и onKeyDown() ) может упростить обслуживание кода и позволяет принимать мета-ключи по умолчанию без необходимости вручную реализовывать проверки мета-ключей в каждом случае. Разрешение всех комбинаций мета-клавиш также может быть более удобным для пользователей, привыкших к различным раскладкам клавиатуры и операционным системам.

Котлин

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)
    }
  }
}

Ява

@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() , проверив KeyEvent.isCtrlPressed() , KeyEvent.isShiftPressed() или KeyEvent.isAltPressed() таким же образом, как указано выше. Это может быть проще поддерживать, если метаповедение является скорее модификацией поведения приложения, чем ярлыком. Например, когда W означает «идти вперед», а Shift + W означает «бежать вперед».

Котлин

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)
  }
}

Ява

@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 :

  • 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, для удобства система устанавливает FLAG_CANCELED для событий ACTION_CANCEL , но в предыдущих версиях этого не происходит.

Андроид 12

В Android 12 (уровень API 32) и более ранних версиях обнаружение отклонения ладони возможно только для событий касания с одним указателем. Если прикосновение ладони является единственным указателем, система отменяет событие, устанавливая ACTION_CANCEL для объекта события движения. Если другие указатели не работают, система устанавливает ACTION_POINTER_UP , которого недостаточно для обнаружения отклонения ладони.

Андроид 13

В Android 13 (уровень API 33) и более поздних версиях, если единственным указателем является прикосновение ладони, система отменяет событие, устанавливая ACTION_CANCEL и FLAG_CANCELED для объекта события движения. Если другие указатели не работают, система устанавливает ACTION_POINTER_UP и FLAG_CANCELED .

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

Приложения для заметок

У ChromeOS есть особая цель: предоставлять пользователям зарегистрированные приложения для создания заметок. Чтобы зарегистрировать приложение в качестве приложения для создания заметок, добавьте в манифест Android следующее:

<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 и нажав Enter.
  6. Нажмите Ctrl + Alt + F1, чтобы вернуться к обычному пользовательскому интерфейсу ChromeOS.
  7. Выйти и снова войти

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

  • Нажмите кнопку стилуса на полке и выберите «Новая заметка» . Это должно открыть пустую заметку к чертежу.
  • Сделайте снимок экрана. На полке выберите кнопку стилуса > Снимок экрана или загрузите изображение. В уведомлении должна быть опция «Аннотировать изображение». Это должно запустить приложение с изображением, готовым к аннотированию.

Поддержка мыши и тачпада

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

Щелкните правой кнопкой мыши

Любые действия, которые заставляют приложение отображать контекстное меню, например касание и удержание элемента списка, также должны реагировать на события щелчка правой кнопкой мыши. Для обработки событий щелчка правой кнопкой мыши приложения должны зарегистрировать View.OnContextClickListener . Подробную информацию о создании контекстного меню см. в разделе Создание контекстных меню .

Котлин

yourView.setOnContextClickListener {
  showContextMenu()
  true
}

Ява

yourView.setOnContextClickListener(v -> {
    showContextMenu();
    return true;
});

Наведите указатель мыши

Разработчики могут сделать макеты своих приложений более совершенными и простыми в использовании, обрабатывая события наведения. Это особенно актуально для пользовательских представлений. Два наиболее распространенных примера:

  • Указание пользователям, имеет ли элемент интерактивное поведение, например, доступен ли он для щелчка или редактирования, путем изменения значка указателя мыши.
  • Добавление визуальной обратной связи к элементам в большом списке или сетке при наведении на них указателя мыши.

Котлин

// 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)
  false // listener did not consume the event.
}

Ява

yourView.setOnHoverListener((view, event) -> {
    addVisualHighlighting(true);
    view.setPointerIcon(PointerIcon
            .getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND));
    return true;
});

Перетащите

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

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

Чтобы добавить поддержку перетаскивания, следуйте документации по перетаскиванию Android и прочтите эту публикацию в блоге ChromeOS .

Особые замечания по ChromeOS

  • Не забудьте запросить разрешение через requestDragAndDropPermissions для доступа к элементам, перетаскиваемым из-за пределов приложения.
  • Элемент должен иметь флаг View.DRAG_FLAG_GLOBAL , чтобы его можно было перетащить в другие приложения.

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

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

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

{% дословно %} {% дословно %} {% дословно %} {% дословно %}