Редактор методов ввода (IME) — это элемент управления, позволяющий пользователям вводить текст. Android предоставляет расширяемую структуру методов ввода, которая позволяет приложениям предоставлять пользователям альтернативные методы ввода, такие как экранные клавиатуры или голосовой ввод. После установки IME пользователь может выбрать один из них в системных настройках и использовать его во всей системе. Одновременно можно включить только один IME.
Чтобы добавить IME в систему Android, создайте приложение Android, содержащее класс, расширяющий InputMethodService . Кроме того, обычно создается активность "настройки", которая передает параметры в службу IME. Вы также можете определить пользовательский интерфейс настроек, который отображается как часть системных настроек.
На этой странице рассматриваются следующие темы:
- Жизненный цикл IME
- Объявление компонентов IME в манифесте приложения
- API IME
- Разработка пользовательского интерфейса для IME
- Отправка текста из IME в приложение.
- Работа с подтипами IME
- Другие соображения, касающиеся медицинской экспертизы.
Если вы раньше не работали с экранными методами ввода, сначала прочтите вводную статью «Экранные методы ввода» .
Жизненный цикл IME
На следующей диаграмме описан жизненный цикл IME:

В следующих разделах описывается, как реализовать пользовательский интерфейс и код, связанные с IME, который следует этому жизненному циклу.
Объявите компоненты IME в манифесте.
В системе Android IME — это приложение Android, содержащее специальную службу IME. В файле манифеста приложения необходимо объявить эту службу, запросить необходимые разрешения, предоставить фильтр намерений, соответствующий действию action.view.InputMethod , и метаданные, определяющие характеристики IME. Кроме того, для предоставления интерфейса настроек, позволяющего пользователю изменять поведение IME, можно определить активность «Настройки», которую можно запустить из системных настроек.
Следующий фрагмент кода объявляет службу IME. Он запрашивает разрешение BIND_INPUT_METHOD , позволяющее службе подключать IME к системе, настраивает фильтр намерений, соответствующий действию android.view.InputMethod , и определяет метаданные для IME:
<!-- Declares the input method service. --> <service android:name="FastInputIME" android:label="@string/fast_input_label" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service>
Следующий фрагмент кода описывает действие настроек для IME. Он содержит фильтр намерений для ACTION_MAIN , указывающий, что это действие является основной точкой входа для приложения IME:
<!-- Optional: an activity for controlling the IME settings. --> <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"> <intent-filter> <action android:name="android.intent.action.MAIN"/> </intent-filter> </activity>
Вы также можете предоставить доступ к настройкам IME непосредственно из его пользовательского интерфейса.
API метода ввода
Классы, специфичные для IME (методов ввода-вывода), находятся в пакетах android.inputmethodservice и android.view.inputmethod . Класс KeyEvent важен для обработки символов клавиатуры.
Центральным элементом интерфейса ввода (IME) является сервисный компонент — класс, расширяющий класс InputMethodService . Помимо реализации стандартного жизненного цикла сервиса, этот класс содержит коллбэки для предоставления пользовательского интерфейса IME, обработки пользовательского ввода и вывода текста в поле, находящееся в фокусе. По умолчанию класс InputMethodService предоставляет большую часть реализации для управления состоянием и видимостью IME, а также для взаимодействия с текущим полем ввода.
Следующие классы также важны:
-
BaseInputConnection - Определяет канал связи от
InputMethodк приложению, получающему ввод. Он используется для чтения текста вокруг курсора, записи текста в текстовое поле и отправки необработанных событий нажатия клавиш приложению. Приложения должны расширять этот класс, а не реализовывать базовый интерфейсInputConnection. -
KeyboardView - Расширение
View, которое отображает клавиатуру и реагирует на события ввода пользователя. Раскладка клавиатуры задается экземпляромKeyboard, который можно определить в XML-файле.
Разработайте пользовательский интерфейс метода ввода.
В интерфейсе ввода (IME) есть два основных визуальных элемента: поле ввода и поле выбора вариантов . Вам нужно реализовать только те элементы, которые соответствуют разрабатываемому методу ввода.
Входное поле
Поле ввода — это пользовательский интерфейс, где пользователь вводит текст с помощью нажатий клавиш, рукописного ввода или жестов. При первом отображении окна ввода система вызывает функцию обратного вызова onCreateInputView() . В вашей реализации этого метода создайте макет, который вы хотите отобразить в окне ввода, и верните этот макет системе. Следующий фрагмент кода демонстрирует пример реализации метода onCreateInputView() :
Котлин
override fun onCreateInputView(): View { return layoutInflater.inflate(R.layout.input, null).apply { if (this is MyKeyboardView) { setOnKeyboardActionListener(this@MyInputMethod) keyboard = latinKeyboard } } }
Java
@Override public View onCreateInputView() { MyKeyboardView inputView = (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null); inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(latinKeyboard); return inputView; }
В этом примере MyKeyboardView — это экземпляр пользовательской реализации KeyboardView , которая отображает Keyboard .
Мнение кандидатов
Представление кандидатов — это пользовательский интерфейс, где IME отображает потенциальные исправления слов или подсказки для выбора пользователем. В жизненном цикле IME система вызывает onCreateCandidatesView() когда готова отобразить представление кандидатов. В вашей реализации этого метода верните макет, отображающий подсказки слов, или верните null, если вы ничего не хотите показывать. Ответ null является поведением по умолчанию, поэтому вам не нужно реализовывать это, если вы не предоставляете подсказки.
Вопросы проектирования пользовательского интерфейса
В этом разделе рассматриваются некоторые аспекты проектирования пользовательского интерфейса для IME (инструментов ввода-вывода).
Поддержка различных размеров экрана
Пользовательский интерфейс вашего IME должен масштабироваться под разные размеры экрана и поддерживать как альбомную, так и портретную ориентацию. В не полноэкранном режиме IME оставьте достаточно места для отображения текстового поля и связанного с ним контекста, чтобы IME занимал не более половины экрана. В полноэкранном режиме IME это не проблема.
Обработка различных типов входных данных
Текстовые поля Android позволяют задавать определенный тип ввода, например, произвольный текст, числа, URL-адреса, адреса электронной почты и поисковые запросы. При реализации нового IME необходимо определить тип ввода для каждого поля и предоставить соответствующий интерфейс. Однако вам не нужно настраивать IME для проверки того, вводит ли пользователь допустимый текст для данного типа ввода. Это задача приложения, которому принадлежит текстовое поле.
Например, вот интерфейс, который предоставляет латинский IME для ввода текста на платформе Android:

А вот и интерфейс, который предоставляет латинский IME для ввода числовых данных на платформе Android:

Когда поле ввода получает фокус и запускается ваш IME, система вызывает onStartInputView() , передавая объект EditorInfo , содержащий подробную информацию о типе ввода и других атрибутах текстового поля. В этом объекте поле inputType содержит тип ввода текстового поля.
Поле inputType представляет собой int , содержащее битовые шаблоны для различных настроек типа ввода. Чтобы проверить его на соответствие типу ввода текстового поля, замаскируйте его константой TYPE_MASK_CLASS следующим образом:
Котлин
inputType and InputType.TYPE_MASK_CLASS
Java
inputType & InputType.TYPE_MASK_CLASS
Шаблон битов типа входных данных может принимать одно из нескольких значений, в том числе:
-
TYPE_CLASS_NUMBER - Текстовое поле для ввода чисел. Как показано на рисунке 3, латинский IME отображает цифровую клавиатуру для полей этого типа.
-
TYPE_CLASS_DATETIME - Текстовое поле для ввода даты и времени.
-
TYPE_CLASS_PHONE - Текстовое поле для ввода телефонных номеров.
-
TYPE_CLASS_TEXT - Текстовое поле для ввода любых поддерживаемых символов.
Эти константы более подробно описаны в справочной документации для InputType .
Поле inputType может содержать другие биты, указывающие на вариант типа текстового поля, например:
-
TYPE_TEXT_VARIATION_PASSWORD - Вариант класса
TYPE_CLASS_TEXTдля ввода паролей. Метод ввода отображает символы вместо фактического текста. -
TYPE_TEXT_VARIATION_URI - Вариант класса
TYPE_CLASS_TEXTдля ввода веб-адресов и других унифицированных идентификаторов ресурсов (URI). -
TYPE_TEXT_FLAG_AUTO_COMPLETE - Вариант типа
TYPE_CLASS_TEXTдля ввода текста, который приложение автоматически дополняет из словаря, поиска или других средств.
При проверке наличия этих вариантов используйте соответствующую константу для маскирования inputType . Доступные константы для маскирования перечислены в справочной документации по InputType .
Отправить текст в приложение
Когда пользователь вводит текст с помощью вашего IME, вы можете отправлять текст в приложение, отправляя отдельные события нажатия клавиш или редактируя текст вокруг курсора в текстовом поле приложения. В любом случае используйте экземпляр InputConnection для передачи текста. Чтобы получить этот экземпляр, вызовите InputMethodService.getCurrentInputConnection() .
Отредактируйте текст вокруг курсора.
При редактировании существующего текста полезными могут быть следующие методы класса BaseInputConnection :
-
getTextBeforeCursor() - Возвращает
CharSequence, содержащий количество запрошенных символов перед текущей позицией курсора. -
getTextAfterCursor() - Возвращает
CharSequence, содержащий количество запрошенных символов после текущей позиции курсора. -
deleteSurroundingText() - Удаляет указанное количество символов до и после текущей позиции курсора.
-
commitText() - Создает
CharSequenceдля текстового поля и устанавливает новую позицию курсора.
Например, следующий фрагмент кода показывает, как заменить четыре символа слева от курсора текстом "Hello!":
Котлин
currentInputConnection.also { ic: InputConnection -> ic.deleteSurroundingText(4, 0) ic.commitText("Hello", 1) ic.commitText("!", 1) }
Java
InputConnection ic = getCurrentInputConnection(); ic.deleteSurroundingText(4, 0); ic.commitText("Hello", 1); ic.commitText("!", 1);
Перед подтверждением изменений подтвердите создание текста.
Если ваш IME предсказывает текст или требует нескольких шагов для составления глифа или слова, вы можете отображать ход выполнения в текстовом поле до тех пор, пока пользователь не подтвердит слово, а затем заменить частично составленный текст завершенным. Вы можете особым образом обработать текст, добавив к нему тег <span> при передаче его в setComposingText() .
Следующий фрагмент кода демонстрирует, как отображать ход выполнения в текстовом поле:
Котлин
currentInputConnection.also { ic: InputConnection -> ic.setComposingText("Composi", 1) ic.setComposingText("Composin", 1) ic.commitText("Composing ", 1) }
Java
InputConnection ic = getCurrentInputConnection(); ic.setComposingText("Composi", 1); ic.setComposingText("Composin", 1); ic.commitText("Composing ", 1);
Перехват событий, связанных с аппаратными клавишами
Несмотря на то, что окно ввода не имеет явного фокуса, оно сначала получает события нажатия аппаратных клавиш и может обрабатывать их или перенаправлять в приложение. Например, вы можете использовать клавиши управления направлением для навигации по пользовательскому интерфейсу при выборе вариантов во время композиции. Вы также можете перехватывать нажатие клавиши «Назад», чтобы закрыть любые диалоговые окна, исходящие из окна ввода.
Для перехвата нажатия аппаратных клавиш переопределите методы onKeyDown() и onKeyUp() .
Вызывайте метод super() для ключей, которые вы не хотите обрабатывать самостоятельно.
Создайте подтип IME.
Подтипы позволяют IME отображать несколько режимов ввода и языков, поддерживаемых IME. Подтип может представлять следующее:
- Локаль, например, en_US или fr_FR
- Режим ввода, например, голос, клавиатура или рукописный ввод.
- Другие стили ввода, формы или свойства, специфичные для данного IME, такие как 10-клавишная или QWERTY-раскладка клавиатуры.
В качестве режима может использоваться любой текст, например, «клавиатура» или «голос». Подтип также может предоставлять комбинацию этих вариантов.
Информация о подтипе используется для диалогового окна переключения IME, доступного из панели уведомлений, а также для настроек IME. Эта информация также позволяет фреймворку напрямую отображать определенный подтип IME. При создании IME используйте механизм подтипов, поскольку он помогает пользователю идентифицировать и переключаться между различными языками и режимами IME.
Определите подтипы в одном из XML-файлов ресурсов метода ввода, используя элемент <subtype> . Следующий фрагмент кода определяет IME с двумя подтипами: подтип клавиатуры для локали США (английский язык) и еще один подтип клавиатуры для французской языковой локали (Франция):
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon"> <subtype android:name="@string/display_name_english_keyboard_ime" android:icon="@drawable/subtype_icon_english_keyboard_ime" android:languageTag="en-US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="somePrivateOption=true" /> <subtype android:name="@string/display_name_french_keyboard_ime" android:icon="@drawable/subtype_icon_french_keyboard_ime" android:languageTag="fr-FR" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="someVariable=30,someInternalOption=false" /> <subtype android:name="@string/display_name_german_keyboard_ime" ... /> </input-method>
Чтобы убедиться, что ваши подтипы правильно обозначены в пользовательском интерфейсе, используйте `%s` для получения метки подтипа, совпадающей с меткой локали подтипа. Это показано в следующих двух фрагментах кода. Первый фрагмент показывает часть XML-файла метода ввода:
<subtype android:label="@string/label_subtype_generic" android:imeSubtypeLocale="en_US" android:icon="@drawable/icon_en_us" android:imeSubtypeMode="keyboard" />
Следующий фрагмент кода является частью файла strings.xml интерфейса ввода (IME). Строковый ресурс label_subtype_generic , используемый определением пользовательского интерфейса метода ввода для установки метки подтипа, определяется следующим образом:
<string name="label_subtype_generic">%s</string>Этот параметр приводит к тому, что отображаемое имя подтипа соответствует языковым настройкам. Например, в любой англоязычной языковой системе отображаемое имя будет «English (United States)».
Выберите подтипы IME в панели уведомлений.
Система Android управляет всеми подтипами, предоставляемыми всеми IME. Подтипы IME рассматриваются как режимы того IME, к которому они относятся. Пользователь может перейти из панели уведомлений или приложения «Настройки» к меню доступных подтипов IME, как показано на следующем рисунке:

Выберите подтипы IME в системных настройках.
Пользователь также может управлять использованием подтипов в панели «Язык и ввод » в системных настройках:

Переключение между подтипами IME
Вы можете предоставить пользователям возможность легко переключаться между подтипами IME, предоставив клавишу переключения, например, значок языка в виде глобуса на клавиатуре. Это повышает удобство использования клавиатуры и делает её более удобной для пользователя. Чтобы включить это переключение, выполните следующие действия:
- В XML-файлах ресурсов метода ввода необходимо указать
supportsSwitchingToNextInputMethod = "true". Ваше объявление должно выглядеть примерно так:<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon" android:supportsSwitchingToNextInputMethod="true">
- Вызовите метод
shouldOfferSwitchingToNextInputMethod(). - Если метод возвращает true, отобразите клавишу переключения.
- Когда пользователь нажимает клавишу переключения, вызовите
switchToNextInputMethod(), передав значение false. Значение false указывает системе обрабатывать все подтипы одинаково, независимо от того, к какому типу ввода они относятся. Указание значения true требует от системы перебора подтипов в текущем типе ввода.
Общие соображения, касающиеся медицинской экспертизы.
Вот ещё несколько моментов, которые следует учитывать при внедрении IME:
- Предоставьте пользователям возможность устанавливать параметры непосредственно из пользовательского интерфейса IME.
- Предоставьте пользователям возможность переключаться на другой IME непосредственно из интерфейса выбора метода ввода, поскольку на устройстве может быть установлено несколько IME.
- Быстро отображайте пользовательский интерфейс метода ввода. Предварительно загружайте или загружайте по запросу любые крупные ресурсы, чтобы пользователи видели метод ввода сразу после нажатия на текстовое поле. Кэшируйте ресурсы и представления для последующих вызовов метода ввода.
- Освободите большие объемы памяти сразу после скрытия окна ввода, чтобы у приложений было достаточно памяти для работы. Используйте отложенное сообщение для освобождения ресурсов, если окно ввода скрыто на несколько секунд.
- Убедитесь, что пользователи могут вводить как можно больше символов для языка или локали, связанных с IME. Пользователи могут использовать знаки препинания в паролях или именах пользователей, поэтому ваш IME должен предоставлять множество различных символов, чтобы пользователи могли ввести пароль и получить доступ к устройству.