Editores de texto personalizados são visualizações que não são
componentes EditText
ou
widgets de texto WebView
, mas
oferecem suporte à entrada de texto implementando o callback
onCreateInputConnection()
,
que é chamado quando uma visualização é focada e o sistema solicita um
InputConnection
para ela.
Uma chamada para
onCheckIsTextEditor()
de um editor de texto personalizado precisa retornar true
.
Suporte à escrita à mão com a stylus em editores de texto personalizados
O Android 14 (nível 34 da API) e versões mais recentes oferecem suporte à entrada da stylus em componentes de entrada de texto padrão do Android por padrão. Consulte Entrada da stylus em campos de texto. No entanto, os campos (ou editores) de entrada de texto personalizados exigem desenvolvimento adicional.
Para criar um editor de texto personalizado, faça o seguinte:
- Ativar iniciação de escrita à mão
- Declarar compatibilidade com escrita à mão
- Suporte a gestos de escrita à mão (selecionar, excluir, inserir etc.)
- Forneça a localização do cursor e outros dados de posição para o IME
- Mostrar o ícone de escrita à mão ao passar o cursor da stylus
Ativar iniciação de escrita à mão
Se uma visualização consistir apenas em um único editor de texto, o sistema de visualização poderá iniciar automaticamente a escrita à mão da stylus para a visualização. Caso contrário, a visualização precisará implementar a própria lógica de início de escrita à mão.
Iniciação automática de escrita à mão
Se uma visualização mostrar um único editor de texto e nenhum outro conteúdo, ela poderá ativar
a iniciação automática de escrita à mão do sistema de visualização chamando
setAutoHandwritingEnabled(true)
.
Com a escrita automática à mão ativada, o movimento da stylus a partir de qualquer lugar dentro dos limites de escrita à mão da visualização inicia automaticamente o modo de escrita à mão. O Editor de método de entrada (IME) recebe os eventos de movimento da stylus e confirma o texto reconhecido.
Iniciação de escrita à mão personalizada
Se uma visualização tiver vários editores de texto ou conteúdo, além de um único editor de texto, ela precisará implementar a própria lógica de início de escrita à mão da seguinte maneira:
Desative a iniciação automática de escrita à mão do sistema de visualização chamando
setAutoHandwritingEnabled(false)
.Acompanhe todos os editores de texto visíveis na visualização.
Monitore os eventos de movimento recebidos pela visualização em
dispatchTouchEvent()
.Quando o movimento da stylus ocorrer dentro dos limites de escrita à mão de um editor de texto, foque no editor de texto (se ele ainda não estiver em foco).
Se o editor ainda não estiver em foco, reinicie o IME (editor de método de entrada, na sigla em inglês) dele com novos conteúdos chamando
InputMethodManager#restartInput()
.Inicie a sessão de escrita à mão da stylus chamando
InputMethodManager#startStylusHandwriting()
.
Se um editor de texto estiver dentro de uma visualização rolável, o movimento da stylus dentro dos
limites de escrita à mão do editor será considerado escrita à mão, não rolagem. Use
ViewParent#requestDisallowInterceptTouchEvent()
para evitar que uma visualização ancestral rolável intercepte eventos de toque de um editor
de texto.
Detalhes da API
MotionEvent#getToolType()
: indica se oMotionEvent
é de uma stylus. Nesse caso, o valor de retorno éTOOL_TYPE_STYLUS
ouTOOL_TYPE_ERASER
.InputMethodManager#isStylusHandwritingAvailable()
: indica se o IME oferece suporte à escrita à mão com a stylus. Chame esse método antes de cada chamada paraInputMethodManager#startStylusHandwriting()
, já que a disponibilidade da escrita à mão pode ter mudado.InputMethodManager#startStylusHandwriting()
: faz com que o IME entre no modo de escrita à mão. Um evento de movimentoACTION_CANCEL
é enviado ao app para cancelar o gesto atual. Os eventos de movimento da stylus não são mais enviados para o app.Os eventos de movimento da stylus do gesto atual que já foram enviados ao app são encaminhados para o IME. O IME é necessário para mostrar uma janela de tinta da stylus em que o IME recebe todos os objetos
MotionEvent
seguintes. O IME confirma texto de escrita à mão reconhecido usando as APIsInputConnection
.Se o IME não puder entrar no modo de escrita à mão, essa chamada de método será um ambiente autônomo.
Declarar compatibilidade com escrita à mão
Ao preencher o argumento
EditorInfo
de
View#onCreateInputConnection(EditorInfo)
, chame
setStylusHandwritingEnabled()
para informar ao IME que o editor de texto oferece suporte à escrita à mão.
Declare os gestos compatíveis usando
setSupportedHandwritingGestures()
e
setSupportedHandwritingGesturePreviews()
.
Suporte a gestos de escrita à mão
Os IMEs podem oferecer suporte a vários gestos de escrita à mão, como circular texto para selecioná-lo ou rabiscar sobre o texto para excluí-lo.
Os editores personalizados implementam
InputConnection#performHandwritingGesture()
e
InputConnection#previewHandwritingGesture()
para oferecer suporte a diferentes
tipos de
HandwritingGesture
,
como
SelectGesture
,
DeleteGesture
e
InsertGesture
.
Declare os gestos de escrita à mão compatíveis ao preencher o argumento EditorInfo
de View#onCreateInputConnection(EditorInfo)
. Consulte a seção Declarar suporte à escrita
à mão.
Detalhes da API
InputConnection#performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)
: implementa gestos. O argumentoHandwritingGesture
contém informações de localização que podem ser usadas para determinar em que parte do texto o gesto será realizado. Por exemplo,SelectGesture
fornece um objetoRectF
que especifica o intervalo de texto selecionado, eInsertGesture
fornece um objetoPointF
que especifica o deslocamento do texto em que o texto será inserido.Use os parâmetros
Executor
eIntConsumer
para enviar o resultado da operação. Quando os argumentos do executor e do consumidor forem fornecidos, use o executor para chamarIntConsumer#accept()
, por exemplo:executor.execute { consumer.accept(HANDWRITING_GESTURE_RESULT_SUCCESS) }
HandwritingGesture#getFallbackText()
: fornece o texto substituto que o IME confirma na posição do cursor se nenhum texto aplicável estiver abaixo da área de um gesto de escrita à mão.Às vezes, o IME não consegue determinar se um gesto da stylus se destina a executar uma operação de gesto ou escrever texto à mão. Um editor de texto personalizado é responsável por determinar a intenção do usuário e realizar a ação adequada (dependendo do contexto) no local do gesto.
Por exemplo, se o IME não puder determinar se o usuário pretendia desenhar um circunflexo para baixo ⋁ para executar um gesto de inserção de espaço ou escrever à mão a letra "v", o IME poderá enviar um
InsertGesture
com o texto substituto "v".Primeiro, o editor precisa tentar executar o gesto de inserção de espaço. Se o gesto não puder ser executado (por exemplo, não houver texto no local especificado), o editor voltará a inserir "v" na posição do cursor.
InputConnection#previewHandwritingGesture(PreviewableHandwritingGesture, CancellationSignal)
: visualiza um gesto em andamento. Por exemplo, conforme o usuário começa a desenhar um círculo ao redor de um texto, uma visualização em tempo real da seleção resultante pode ser mostrada e atualizada continuamente à medida que o usuário continua desenhando. Apenas determinados tipos de gestos podem ser visualizados. ConsultePreviewableHandwritingGesture
.O parâmetro
CancellationSignal
pode ser usado pelo IME para cancelar a visualização. Se outros eventos interromperem a visualização (por exemplo, se o texto for alterado de maneira programática ou a ocorrência de novos comandosInputConnection
), o editor personalizado poderá cancelar a visualização.Os gestos de visualização são apenas para exibição e não podem mudar o estado do editor. Por exemplo, uma visualização de
SelectGesture
oculta o intervalo de seleção atual do editor e destaca o intervalo de visualização de gesto. No entanto, depois que a visualização for cancelada, o editor vai restaurar o intervalo de seleção anterior.
Forneça a localização do cursor e outros dados de posição
No modo de escrita à mão, o IME pode solicitar a localização do cursor e outros dados de posição
usando
InputConnection#requestCursorUpdates()
.
O editor personalizado responde com uma chamada para
InputMethodManager#updateCursorAnchorInfo(View,
CursorAnchorInfo)
.
Os dados em
CursorAnchorInfo
relevantes para a escrita à mão da stylus são fornecidos pelos seguintes
métodos
CursorAnchorInfo.Builder
:
setInsertionMarkerLocation()
: define o local do cursor. O IME usa o valor para animar a tinta de escrita à mão no local do cursor.setEditorBoundsInfo()
: define os limites do editor e da escrita à mão. O IME usa esses dados para posicionar a barra de ferramentas de escrita à mão dele na tela.addVisibleLineBounds()
: define os limites de todas as linhas de texto visíveis (ou parcialmente visíveis) do editor. O IME usa os limites de linha para melhorar a precisão no reconhecimento de gestos de escrita à mão.setTextAppearanceInfo()
: define a aparência do texto com informações derivadas do campo de entrada de texto. O IME usa as informações para definir o estilo da tinta de escrita à mão.
Mostrar o ícone de escrita à mão ao passar o cursor da stylus
Mostre o ícone de escrita à mão da stylus quando ela passar o cursor sobre os
limites de escrita à mão do editor de texto personalizado e o IME selecionado oferecer suporte à
escrita à mão com a stylus
(InputMethodManager#isStylusHandwritingAvailable()
).
Modifique
View#onResolvePointerIcon()
para receber um ícone de passar o cursor para a escrita à mão da stylus. Na substituição, chame
PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING)
para acessar o ícone de passar o cursor por escrita à mão da stylus do sistema.