Un editor de método de entrada (IME) es un control de usuario que permite que los usuarios ingresen texto. Android proporciona un framework de método de entrada extensible que permite que las aplicaciones ofrezcan a los usuarios métodos de entrada alternativos, como teclados en pantalla o entrada de voz. Después de instalar los IME, el usuario puede seleccionar uno en la configuración del sistema y usarlo en todo el sistema. Solo se puede habilitar un IME a la vez.
Para agregar un IME al sistema Android, crea una aplicación para Android que contenga una clase que extienda InputMethodService.
Además, por lo general, creas una actividad de "configuración" que pasa opciones al servicio de IME. También
puedes definir una IU de configuración que se muestre como parte de la configuración del sistema.
En esta página, se abordan los siguientes temas:
- Ciclo de vida del IME
- Cómo declarar componentes de IME en el manifiesto de la aplicación
- La API de IME
- Cómo diseñar una IU de IME
- Envía texto de un IME a una aplicación
- Cómo trabajar con subtipos de IME
- Otras consideraciones sobre el IME
Si no trabajaste con IME, primero lee el artículo introductorio Métodos de entrada en pantalla.
El ciclo de vida del IME
En el siguiente diagrama, se describe el ciclo de vida de un IME:
En las siguientes secciones, se describe cómo implementar la IU y el código asociados con un IME que sigue este ciclo de vida.
Cómo declarar componentes de IME en el manifiesto
En el sistema Android, un IME es una aplicación que contiene un servicio especial de IME. El archivo de manifiesto de la aplicación debe declarar el servicio, solicitar los permisos necesarios, proporcionar un filtro de intents que coincida con la acción action.view.InputMethod y proporcionar metadatos que definan las características del IME. Además, para proporcionar una interfaz de configuración que permita al usuario modificar el comportamiento del IME, puedes definir una actividad de "configuración" que se pueda iniciar desde la configuración del sistema.
El siguiente fragmento declara un servicio del IME. Solicita el permiso BIND_INPUT_METHOD para permitir que el servicio conecte el IME al sistema, configura un filtro de intents que coincida con la acción android.view.InputMethod y define los metadatos para el 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>
En el siguiente fragmento, se declara la actividad de configuración del IME. Tiene un filtro de intents para ACTION_MAIN que indica que esta actividad es el punto de entrada principal de la aplicación de 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>
También puedes proporcionar acceso a la configuración del IME directamente desde su IU.
La API del método de entrada
Las clases específicas de los IME se encuentran en los paquetes android.inputmethodservice y android.view.inputmethod. La clase KeyEvent es importante para controlar los caracteres del teclado.
La parte central de un IME es un componente de servicio, una clase que extiende InputMethodService. Además de implementar el ciclo de vida normal del servicio, esta clase tiene devoluciones de llamada para proporcionar la IU de tu IME, controlar la entrada del usuario y entregar texto al campo que tiene el foco. De forma predeterminada, la clase InputMethodService proporciona la mayor parte de la implementación para administrar el estado y la visibilidad del IME, y comunicarse con el campo de entrada actual.
Las siguientes clases también son importantes:
BaseInputConnection-
Define el canal de comunicación desde un
InputMethodhasta la aplicación que recibe su entrada. Lo usas para leer texto alrededor del cursor, confirmar el mensaje en el cuadro de texto y enviar eventos clave sin procesar a la aplicación. Las aplicaciones deben extender esta clase en lugar de implementar la interfaz baseInputConnection. KeyboardView-
Es una extensión de
Viewque renderiza un teclado y responde a los eventos de entrada del usuario. El diseño del teclado se especifica con una instancia deKeyboard, que puedes definir en un archivo en formato XML.
Cómo diseñar la IU del método de entrada
Hay dos elementos visuales principales para un IME: la vista de entrada y la vista de candidatos. Solo debes implementar los elementos que sean relevantes para el método de entrada que estás diseñando.
Vista Entrada
La vista de entrada es la IU en la que el usuario ingresa texto en forma de clics de teclas, escritura a mano o gestos. Cuando el IME se muestra por primera vez, el sistema llama a la devolución de llamada onCreateInputView(). En tu implementación de este método, crea el diseño que quieras mostrar en la ventana del IME y devuélvelo al sistema. En el siguiente fragmento, se muestra un ejemplo de implementación del método onCreateInputView():
Kotlin
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; }
En este ejemplo, MyKeyboardView es una instancia de una implementación personalizada de KeyboardView que renderiza un Keyboard.
Vista Candidatos
La vista de candidatos es la IU en la que el IME muestra posibles correcciones o sugerencias de palabras para que el usuario las seleccione. En el ciclo de vida del IME, el sistema llama a onCreateCandidatesView() cuando está listo para mostrar la vista de candidatos. En tu implementación de este método, muestra un diseño que incluya sugerencias de palabras o un valor nulo si no quieres mostrar nada. Una respuesta nula es el comportamiento predeterminado, por lo que no tienes que implementar esto si no proporcionas sugerencias.
Consideraciones sobre el diseño de la IU
En esta sección, se describen algunas consideraciones de diseño de la IU para los IME.
Cómo procesar varios tamaños de pantalla
La IU de tu IME debe poder ajustarse a diferentes tamaños de pantalla y controlar las orientaciones horizontal y vertical. En el modo de IME que no es de pantalla completa, deja suficiente espacio para que la aplicación muestre el campo de texto y cualquier contexto asociado, de modo que el IME no ocupe más de la mitad de la pantalla. En el modo de IME de pantalla completa, esto no es un problema.
Cómo procesar diferentes tipos de entrada
Los campos de texto de Android te permiten establecer un tipo de entrada específico, como texto de formato libre, números, URLs, direcciones de correo electrónico y cadenas de búsqueda. Cuando implementes un IME nuevo, detecta el tipo de entrada de cada campo y proporciona la interfaz adecuada para él. Sin embargo, no es necesario que configures tu IME para verificar si el usuario ingresa texto válido para el tipo de entrada. Esta es la responsabilidad de la aplicación propietaria del campo de texto.
Por ejemplo, esta es la interfaz que proporciona el IME latino para la entrada de texto de la plataforma de Android:
Esta es la interfaz que proporciona el IME latino para la entrada numérica de la plataforma de Android:
Cuando un campo de entrada recibe el foco y se inicia tu IME, el sistema llama a onStartInputView() y pasa un objeto EditorInfo que contiene detalles sobre el tipo de entrada y otros atributos del campo de texto. En este objeto,
el campo
inputType
contiene el tipo de entrada del campo de texto.
El campo inputType es un int que contiene patrones de bits para varios parámetros de configuración de tipo de entrada. Para probarlo con el tipo de entrada del campo de texto, enmascáralo con la constante TYPE_MASK_CLASS, de la siguiente manera:
Kotlin
inputType and InputType.TYPE_MASK_CLASS
Java
inputType & InputType.TYPE_MASK_CLASS
El patrón de bits del tipo de entrada puede tener uno de varios valores, incluidos los siguientes:
TYPE_CLASS_NUMBER- Es un campo de texto para ingresar números. Como se ilustra en la figura 3, el IME latino muestra un teclado numérico para los campos de este tipo.
TYPE_CLASS_DATETIME- Un campo de texto para ingresar una fecha y hora.
TYPE_CLASS_PHONE- Es un campo de texto para ingresar números de teléfono.
TYPE_CLASS_TEXT- Es un campo de texto para ingresar cualquier carácter admitido.
Estas constantes se describen con más detalle en la documentación de referencia de InputType.
El campo inputType puede contener otros bits que indiquen una variante del tipo de campo de texto, como los siguientes:
TYPE_TEXT_VARIATION_PASSWORD- Es una variante de
TYPE_CLASS_TEXTpara ingresar contraseñas. El método de entrada muestra dingbats en lugar del texto real. TYPE_TEXT_VARIATION_URI- Es una variante de
TYPE_CLASS_TEXTpara ingresar URLs web y otros identificadores uniformes de recursos (URI). TYPE_TEXT_FLAG_AUTO_COMPLETE- Es una variante de
TYPE_CLASS_TEXTpara ingresar texto que la aplicación autocompleta desde un diccionario, una búsqueda o alguna otra función.
Enmascara inputType con la constante adecuada cuando pruebes estas variantes. Las constantes de máscara disponibles se enumeran en la documentación de referencia de InputType.
Cómo enviar texto a la aplicación
A medida que el usuario ingresa texto con tu IME, puedes enviar texto a la aplicación enviando eventos de teclas individuales o editando el texto alrededor del cursor en el campo de texto de la aplicación. En cualquier caso, usa una instancia de InputConnection para entregar el texto. Para obtener esta instancia, llama a InputMethodService.getCurrentInputConnection().
Cómo editar el texto que aparece alrededor del cursor
Cuando edites texto existente, algunos métodos útiles en BaseInputConnection son los siguientes:
-
getTextBeforeCursor() - Devuelve un
CharSequenceque contiene la cantidad de caracteres solicitados antes de la posición actual del cursor. -
getTextAfterCursor() - Devuelve un
CharSequenceque contiene la cantidad de caracteres solicitados después de la posición actual del cursor. -
deleteSurroundingText() - Borra la cantidad especificada de caracteres antes y después de la posición actual del cursor.
-
commitText() - Confirma un
CharSequenceen el campo de texto y establece una nueva posición del cursor.
Por ejemplo, en el siguiente fragmento, se muestra cómo reemplazar los cuatro caracteres a la izquierda del cursor por el texto "Hello!":
Kotlin
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);
Admite la composición de texto antes de confirmarlo
Si tu IME predice texto o requiere varios pasos para componer un glifo o una palabra, puedes mostrar el progreso en el campo de texto hasta que el usuario confirme la palabra y, luego, puedes reemplazar la composición parcial por el texto completo. Puedes darle un tratamiento especial al texto agregándole un span cuando lo pases a setComposingText().
En el siguiente fragmento, se muestra cómo indicar el progreso en un campo de texto:
Kotlin
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);
Cómo interceptar eventos clave de hardware
Aunque la ventana del método de entrada no tiene un enfoque explícito, recibe primero los eventos de teclas de hardware y puede consumirlos o reenviarlos a la aplicación. Por ejemplo, es posible que quieras consumir las teclas de dirección para navegar dentro de la IU y seleccionar candidatos durante la composición. También puedes interceptar la tecla Atrás para descartar cualquier diálogo que se origine en la ventana del método de entrada.
Para interceptar las teclas de hardware, anula onKeyDown() y onKeyUp().
Llama al método super() para las claves que no quieras controlar por tu cuenta.
Cómo crear un subtipo de IME
Los subtipos permiten que el IME exponga varios modos de entrada y lenguajes compatibles con un IME. Un subtipo puede representar lo siguiente:
- Un parámetro de configuración regional, como en_US o fr_FR
- Un modo de entrada, como voz, teclado o escritura a mano
- Otros estilos, formas o propiedades de entrada específicos del IME, como los diseños de teclado de 10 teclas o QWERTY
El modo puede ser cualquier texto, como "teclado" o "voz". Un subtipo también puede exponer una combinación de estos.
La información de subtipo se usa para un diálogo de selector de IME que está disponible en la barra de notificaciones y para la configuración de IME. La información también permite que el framework muestre directamente un subtipo específico de un IME. Cuando compiles un IME, usa la función de subtipo, ya que ayuda al usuario a identificar y cambiar entre diferentes idiomas y modos de IME.
Define subtipos en uno de los archivos de recursos XML del método de entrada con el elemento <subtype>. En el siguiente fragmento de código, se define un IME con dos subtipos: un subtipo de teclado para la configuración regional de inglés de EE.UU. y otro subtipo de teclado para la configuración regional de francés de Francia:
<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>
Para asegurarte de que tus subtipos estén etiquetados correctamente en la IU, usa `%s` para obtener una etiqueta de subtipo que sea igual a la etiqueta de configuración regional del subtipo. Esto se demuestra en los siguientes dos fragmentos de código. En el primer fragmento, se muestra parte del archivo en formato XML del método de entrada:
<subtype android:label="@string/label_subtype_generic" android:imeSubtypeLocale="en_US" android:icon="@drawable/icon_en_us" android:imeSubtypeMode="keyboard" />
El siguiente fragmento es parte del archivo strings.xml del IME. El recurso de cadenas label_subtype_generic, que usa la definición de la IU del método de entrada para establecer la etiqueta del subtipo, se define de la siguiente manera:
<string name="label_subtype_generic">%s</string>Este parámetro de configuración hace que el nombre visible del subtipo coincida con el parámetro de configuración regional. Por ejemplo, en cualquier configuración regional en inglés, el nombre visible es “Inglés (Estados Unidos)”.
Cómo seleccionar subtipos de IME de la barra de notificaciones
El sistema Android administra todos los subtipos expuestos por todos los IME. Los subtipos de IME se tratan como modos del IME al que pertenecen. El usuario puede navegar desde la barra de notificaciones o la app de Configuración hasta un menú de subtipos de IME disponibles, como se muestra en la siguiente figura:
Cómo seleccionar los subtipos de IME desde Configuración del sistema
El usuario también puede controlar cómo se usan los subtipos en el panel de configuración Idioma y entrada de la configuración del sistema:
Cómo alternar entre subtipos de IME
Para permitir que los usuarios cambien fácilmente entre subtipos de IME, puedes proporcionar una tecla de cambio, como el ícono de idioma con forma de globo terráqueo en el teclado. Esto mejora la usabilidad del teclado y es conveniente para el usuario. Para habilitar este cambio, sigue estos pasos:
- Declara
supportsSwitchingToNextInputMethod = "true"en los archivos de recursos XML del método de entrada. Tu declaración debe ser similar al siguiente fragmento de código:<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">
- Llama al método
shouldOfferSwitchingToNextInputMethod(). - Si arroja un valor verdadero, muestra una tecla de cambio.
- Cuando el usuario presione la tecla de cambio, llama a
switchToNextInputMethod()y pasa el valor falso. Un valor de false le indica al sistema que trate todos los subtipos por igual, independientemente del IME al que pertenezcan. Si se especifica true, el sistema debe recorrer los subtipos en el IME actual.
Consideraciones generales de IME
Aquí hay otros aspectos que debes tener en cuenta cuando implementes tu IME:
- Proporciona una forma para que los usuarios configuren opciones directamente desde la IU del IME.
- Proporciona una forma para que los usuarios cambien a un IME diferente directamente desde la IU del método de entrada, ya que es posible que haya varios IME instalados en el dispositivo.
- Abre la IU del IME rápido. Precarga o carga a pedido cualquier recurso grande para que los usuarios vean el IME en cuanto presionen un campo de texto. Recursos de caché y vistas para invocaciones posteriores del método de entrada.
- Liberar las asignaciones de memoria grandes inmediatamente después de que se oculte la ventana del método de entrada para que las aplicaciones tengan suficiente memoria para ejecutarse Usa un mensaje retrasado para liberar recursos si el IME se oculta durante unos segundos.
- Asegúrate de que los usuarios puedan ingresar tantos caracteres como sea posible para el idioma o la configuración regional asociados con el IME. Es posible que los usuarios usen signos de puntuación en las contraseñas o los nombres de usuario, por lo que tu IME debe proporcionar muchos caracteres diferentes para permitir que los usuarios ingresen una contraseña y accedan al dispositivo.