Um Editor de método de entrada (IME, na sigla em inglês) é um controle que permite que os usuários insiram texto. O Android oferece um framework de método de entrada extensível que permite que os aplicativos forneçam aos usuários métodos de entrada alternativos, como teclado na tela ou até mesmo entrada de fala. Depois de instalar os IMEs escolhidos, o usuário pode selecionar qual deles usar nas configurações do sistema e usá-lo em todo o sistema. Só um IME pode ser ativado por vez.
Para adicionar um IME ao sistema Android, crie um aplicativo para Android
que contenha uma classe que estenda InputMethodService
. Além
disso, você geralmente precisa criar uma atividade de "configurações" que transmita opções para o serviço do IME. Você
também pode definir uma IU de configurações que é exibida como parte das configurações do sistema.
Este guia abrange o seguinte:
- O ciclo de vida do IME
- Como declarar componentes do IME no manifesto do aplicativo
- A API IME
- Como criar uma IU do IME
- Como enviar texto de um IME para um aplicativo
- Como trabalhar com subtipos de IME
Se você nunca trabalhou com IMEs, leia o artigo introdutório Métodos de entrada na tela (link em inglês) antes de começar.
O ciclo de vida do IME
O diagrama a seguir descreve o ciclo de vida de um IME:

Figura 1. O ciclo de vida de um IME.
As seções a seguir descrevem como implementar a IU e o código associado a um IME que segue esse ciclo de vida.
Declarar os componentes do IME no manifesto
No sistema Android, um IME é um aplicativo para Android que contém um serviço de IME especial.
O arquivo de manifesto do aplicativo precisa declarar o serviço, solicitar as permissões necessárias,
fornecer um filtro de intent que corresponda à ação action.view.InputMethod
e
fornecer metadados com as características do IME. Além disso, para fornecer uma interface de
configurações que permita ao usuário modificar o comportamento do IME, você pode definir uma atividade de
"configurações" que possa ser ativada nas configurações do sistema.
O snippet a seguir declara um serviço de IME. Ele solicita a permissão
BIND_INPUT_METHOD
para permitir que o serviço conecte o IME
ao sistema, configura um filtro de intent que corresponda à ação
android.view.InputMethod
e define metadados para o 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>
O próximo snippet declara a atividade de configurações do IME. Ela tem um filtro de intent para
ACTION_MAIN
que indica que essa atividade é o ponto de entrada
principal para o aplicativo 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>
Você também pode fornecer acesso às configurações do IME diretamente na IU dele.
A API do método de entrada
Classes específicas para IMEs são encontradas nos pacotes android.inputmethodservice
e
android.view.inputmethod
. A classe KeyEvent
é
importante para lidar com caracteres do teclado.
A parte central de um IME é um componente de serviço, uma classe que estende
InputMethodService
. Além de implementar o
ciclo de vida normal do serviço, essa classe tem callbacks para fornecer a IU do seu IME, processar a entrada
do usuário e enviar texto para o campo em foco no momento. Por padrão, a classe
InputMethodService
fornece a maior parte da implementação
para gerenciar o estado e a visibilidade do IME e se comunicar com o campo
de entrada atual.
As seguintes classes também são importantes:
BaseInputConnection
-
Define o canal de comunicação de um
InputMethod
para o aplicativo que está recebendo a entrada. Você pode usá-lo para ler o texto ao redor do cursor, confirmar o texto para a caixa de texto e enviar eventos de chave brutos para o aplicativo. Os splicativos precisam estender essa classe, em vez de implementar a interface baseInputConnection
. KeyboardView
-
Uma extensão de
View
que renderiza um teclado e responde a eventos de entrada do usuário. O layout do teclado é especificado por uma instância deKeyboard
, que você pode definir em um arquivo XML.
Projetar a IU do método de entrada
Há dois elementos visuais principais para um IME: a visualização de entrada e a visualização candidata. Você só precisa implementar os elementos relevantes para o método de entrada que está criando.
Visualização de entrada
A visualização de entrada é a IU em que o usuário insere texto na forma de cliques em teclas, escrita à mão ou
gestos. Quando o IME é exibido pela primeira vez, o sistema chama o callback
onCreateInputView()
. Na
implementação desse método, você cria o layout que quer exibir na janela do
IME e retorna o layout para o sistema. Este snippet é um exemplo de implementação do 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; }
Nesse exemplo, MyKeyboardView
é uma instância de uma implementação
personalizada de
KeyboardView
que processa um
Keyboard
.
Visualização candidata
A visualização candidata é a IU em que o IME exibe possíveis correções de palavras ou
sugestões para o usuário selecionar. No ciclo de vida do IME, o sistema chama
onCreateCandidatesView()
quando está pronto
para exibir a visualização candidata. Na sua implementação desse método, retorne um layout que
mostre sugestões de palavras ou que retorne "nulo", se você não quiser exibir nada. Uma resposta nula é
o comportamento padrão. Portanto, não é necessário implementá-la se você não fornece sugestões.
Considerações sobre o design da IU
Esta seção descreve algumas considerações específicas de design da IU para IMEs.
Processar vários tamanhos de tela
A IU do seu IME precisa poder ser dimensionada para diferentes tamanhos de tela, além de lidar com as orientações paisagem e retrato. No modo IME de tela normal, deixe espaço suficiente para que o aplicativo mostre o campo de texto e qualquer contexto associado para que não mais que a metade da tela seja ocupada pelo IME. No modo IME de tela cheia, isso não é um problema.
Processar diferentes tipos de entrada
Os campos de texto do Android permitem que você defina um tipo de entrada específico, como texto de forma livre, números, URLs, endereços de e-mail e strings de pesquisa. Ao implementar um novo IME, é necessário detectar o tipo de entrada de cada campo e fornecer a interface adequada para ele. No entanto, você não precisa configurar o IME para verificar se o usuário inseriu um texto válido para o tipo de entrada. Isso é responsabilidade do aplicativo ao qual o campo de texto pertence.
Por exemplo, veja capturas de tela das interfaces que o IME Latin, fornecido com a plataforma Android, oferece para entradas de texto e números de telefone:


Figura 2. Tipos de entrada do IME Latin.
Quando um campo de entrada recebe foco e seu IME é iniciado, o sistema chama
onStartInputView()
, transmitindo um objeto EditorInfo
que contém detalhes sobre
o tipo de entrada e outros atributos do campo de texto. Nesse objeto, o campo
inputType
contém o tipo de entrada do campo de
texto.
O campo inputType
é um int
que contém padrões de bits para várias configurações de tipo de entrada. Para testar o tipo de entrada
do campo de texto, mascare-o com a constante TYPE_MASK_CLASS
desta
forma:
Kotlin
inputType and InputType.TYPE_MASK_CLASS
Java
inputType & InputType.TYPE_MASK_CLASS
O padrão de bits do tipo de entrada pode ter um de vários valores, incluindo:
TYPE_CLASS_NUMBER
- Um campo de texto para inserir números. Como ilustrado na captura de tela anterior, o IME Latin exibe um teclado numérico para campos desse tipo.
TYPE_CLASS_DATETIME
- Um campo de texto para inserir uma data e hora.
TYPE_CLASS_PHONE
- Um campo de texto para inserir números de telefone.
TYPE_CLASS_TEXT
- Um campo de texto para inserir todos os caracteres compatíveis.
Essas constantes são descritas em mais detalhes na documentação de referência para
InputType
.
O campo inputType
pode conter outros bits que
indicam uma variante do tipo de campo de texto como:
TYPE_TEXT_VARIATION_PASSWORD
-
Uma variante de
TYPE_CLASS_TEXT
para inserir senhas. O método de entrada exibirá dingbats, em vez do texto real. TYPE_TEXT_VARIATION_URI
-
Uma variante de
TYPE_CLASS_TEXT
para inserir URLs da Web e outros Identificadores uniformes de recurso (URIs, na sigla em inglês). TYPE_TEXT_FLAG_AUTO_COMPLETE
-
Uma variante de
TYPE_CLASS_TEXT
para inserir texto que o aplicativo preenche automaticamente a partir de um dicionário, pesquisa ou outro recurso.
Lembre-se de mascarar inputType
com a constante adequada
ao testar essas variantes. As constantes de máscara disponíveis estão listadas na
documentação de referência para InputType
.
Cuidado: no seu IME, lembre-se de processar o texto corretamente ao enviá-lo para um campo de senha. Oculte a senha na IU tanto na visualização de entrada quanto na visualização candidata. Lembre-se também de que senhas não devem ser armazenadas em um dispositivo. Para saber mais, consulte o guia Dicas de segurança.
Enviar texto para o aplicativo
À medida que o usuário insere dados com seu IME, é possível enviar textos para o aplicativo, enviando
eventos de teclas individuais ou editando o texto ao redor do cursor no campo de texto do
aplicativo. De qualquer forma, é possível usar uma instância de InputConnection
para entregar esse texto. Para acessar essa instância, chame
InputMethodService.getCurrentInputConnection()
.
Editar o texto ao redor do cursor
Ao editar o texto existente em um campo, alguns dos métodos mais
úteis em BaseInputConnection
são:
-
getTextBeforeCursor()
-
Retorna um
CharSequence
contendo o número de caracteres solicitados antes da posição atual do cursor. -
getTextAfterCursor()
-
Retorna um
CharSequence
contendo o número de caracteres solicitados após a posição atual do cursor. -
deleteSurroundingText()
- Exclui o número específico de caracteres antes e depois da posição atual do cursor.
-
commitText()
-
Confirma um
CharSequence
para o campo de texto e define uma nova posição do cursor.
Por exemplo, o snippet a seguir mostra como substituir os quatro caracteres à esquerda do cursor pelo 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);
Como escrever um texto antes de confirmar
Se o IME fizer previsão de texto ou exigir várias etapas para compor um glifo ou
uma palavra, você poderá mostrar o progresso no campo de texto até que o usuário confirme a palavra. Em seguida, você
pode substituir a composição parcial pelo texto concluído. Você pode dar tratamento especial ao
texto adicionando um "span" a ele ao transmitir ele para
setComposingText()
.
O snippet a seguir mostra como exibir o progresso em um 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);
As seguintes capturas de tela mostram como isso aparece para o usuário:



Figura 3. Escrever um texto antes de confirmar.
Interceptar eventos de chave de hardware
Embora a janela do método de entrada não tenha foco explícito, ela recebe os eventos de teclas de hardware primeiro e pode optar por consumi-los ou encaminhá-los ao aplicativo. Por exemplo, você pode consumir as teclas direcionais para navegar na IU e fazer a seleção de candidatos durante a composição. Você também pode interceptar a tecla "Voltar" para dispensar qualquer pop-up proveniente da janela do método de entrada.
Para interceptar teclas do hardware, substitua
onKeyDown()
e onKeyUp()
.
Lembre-se de chamar o método super()
para as chaves que você não quer manipular.
Criar um subtipo de IME
Os subtipos permitem que o IME exponha diversos modelos de entrada e idiomas compatíveis com o IME. Um subtipo pode representar:
- uma localidade, como en_US ou fr_FR;
- um modo de entrada, como voz, teclado ou escrita à mão;
- outros estilos de entrada, formulários ou propriedades específicos do IME, como layouts de teclado qwerty ou com 10 teclas.
Basicamente, o modo pode ser qualquer texto como "keyboard", "voice" e assim por diante. Um subtipo também pode expor uma combinação deles.
As informações de subtipo são usadas para uma caixa de diálogo do alternador de IME, que está disponível na barra de notificação e também nas configurações do IME. As informações também permitem que o framework exiba diretamente um subtipo específico de um IME. Use o recurso de subtipo ao criar um IME, porque ele ajuda o usuário a identificar e alternar entre diferentes idiomas e modos do IME.
Os subtipos são definidos em um dos arquivos de recurso XML do método de entrada, usando o elemento
<subtype>
. O snippet a seguir define um IME com dois
subtipos: um subtipo de teclado para a localidade em inglês americano e outro para a
localidade em francês da França:
<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:imeSubtypeLanguage="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:imeSubtypeLanguage="fr_FR" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="foobar=30,someInternalOption=false" /> <subtype android:name="@string/display_name_german_keyboard_ime" ... /> </input-method>
Para garantir que os subtipos sejam marcados corretamente na IU, use %s para receber um marcador de subtipo que seja igual ao marcador de localidade do subtipo. Isso é demonstrado nos próximos dois snippets. O primeiro snippet mostra parte do arquivo XML do método de entrada:
<subtype android:label="@string/label_subtype_generic" android:imeSubtypeLocale="en_US" android:icon="@drawable/icon_en_us" android:imeSubtypeMode="keyboard" />
O snippet seguinte faz parte do arquivo strings.xml
do IME. O recurso de
string label_subtype_generic
, que é usado pela definição da IU do método de entrada para
configurar o marcador do subtipo, é definido como:
<string name="label_subtype_generic">%s</string>
Essa configuração faz com que o nome de exibição do subtipo corresponda à configuração de localidade. Por exemplo, em qualquer localidade em inglês, o nome de exibição é "English (United States)".
Escolher os subtipos de IME na barra de notificação
O sistema Android gerencia todos os subtipos expostos por todos os IMEs. Os subtipos de IME são tratados como modos do IME aos quais eles pertencem. Na barra de notificações, um usuário pode selecionar um subtipo disponível para o IME definido atualmente, conforme mostrado nesta captura de tela:

Figura 4. Como escolher um subtipo de IME na barra de notificação.

Figura 5. Definição de preferências de subtipo nas configurações do sistema.
Escolher os subtipos de IME nas configurações do sistema
O usuário pode controlar como os subtipos são usados no painel de configurações "Idioma e entrada" nas "Configurações do sistema".

Figura 6. Escolha de um idioma para o IME.
Alternar entre os subtipos de IME
Você pode permitir que os usuários alternem facilmente entre vários subtipos de IME fornecendo um botão de alternância como parte do teclado, por exemplo, o ícone de idioma em forma de globo. Isso melhora muito a usabilidade do teclado e pode ajudar a evitar a frustração do usuário. Para ativar essa alternância, execute as seguintes etapas:
- Declare
supportsSwitchingToNextInputMethod = "true"
nos arquivos de recursos XML do método de entrada. Sua declaração precisa ser semelhante a este snippet:<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">
- Chame o método
shouldOfferSwitchingToNextInputMethod()
. - Se o método retornar "verdadeiro", exiba um botão de alternância.
- Quando o usuário tocar no botão de alternância, chame
switchToNextInputMethod()
transmitindo "falso" para o segundo parâmetro. Um valor "falso" instrui o sistema a tratar todos os subtipos igualmente, independentemente do IME a que eles pertençam. Especificar "ver5dadeiro" exige que o sistema percorra subtipos no IME atual.
Atenção: antes do Android 5.0 (API de nível 21),
switchToNextInputMethod()
não tem conhecimento do atributo supportsSwitchingToNextInputMethod
. Se o usuário alternar
para um IME sem um botão de alternância, ele poderá ficar preso nesse IME e não conseguir sair dele facilmente.
Considerações gerais sobre IME
Veja a seguir algumas outras coisas que você precisa considerar ao implementar seu IME:
- Ofereça uma forma para que os usuários ativem opções diretamente da IU do IME.
- Como vários IMEs podem estar instalados no dispositivo, forneça uma maneira para o usuário alternar para outro IME diretamente da IU do método de entrada.
- Chame a IU do IME rapidamente. Carregue previamente ou carregue sob demanda os recursos grandes para que os usuários vejam o IME assim que tocarem em um campo de texto. Armazene em cache recursos e visualizações para invocações subsequentes do método de entrada.
- Por outro lado, você precisa liberar grandes alocações de memória logo após a janela do método de entrada ficar oculta, para que os aplicativos tenham memória suficiente para serem executados. Considere o uso de uma mensagem atrasada para liberar recursos se o IME ficar oculto por alguns segundos.
- Verifique se os usuários podem inserir o máximo de caracteres possível para o idioma ou a localidade associada ao IME. Lembre-se de que os usuários podem usar pontuação em senhas ou nomes de usuário. Portanto, o IME precisa fornecer diferentes caracteres para permitir que os usuários digitem uma senha e acessem o dispositivo.