Eu tenho um EditText
campo com um Observador de Texto do Cliente. Em um trecho de código, preciso alterar o valor no EditText que utilizo .setText("whatever")
.
O problema é que, assim que faço essa alteração, o afterTextChanged
método é chamado, o que cria um loop infinito. Como posso alterar o texto sem acionar afterTextChanged?
Preciso do texto no método afterTextChanged, portanto, não sugiro remover o TextWatcher
.
java
android
event-handling
infinite-loop
user1143767
fonte
fonte
Resposta curta
Você pode verificar qual Visualização tem o foco atualmente para distinguir entre os eventos disparados pelo usuário e pelo programa.
Resposta longa
Como complemento à resposta curta: Caso
myEditText
já tenha o foco quando você alterar programaticamente o texto que deve chamarclearFocus()
, então você ligasetText(...)
e depois pede novamente o foco. Seria uma boa ideia colocar isso em uma função de utilidade:Para Kotlin:
Como o Kotlin oferece suporte a funções de extensão, sua função de utilitário pode ser parecida com esta:
fonte
getActivity().getCurrentFocus()
e kotlinactivity?.currentFocus
hasFocus()
diretamente noEditText
.Uso:
Você pode sentir um pequeno atraso ao inserir texto rapidamente se estiver usando editText.setText () em vez de editable.replace () .
fonte
Truque fácil de corrigir ... desde que sua lógica para derivar o novo valor do texto de edição seja idempotente (o que provavelmente seria, mas apenas dizendo). Em seu método de ouvinte, modifique o texto de edição apenas se o valor atual for diferente da última vez que você modificou o valor.
por exemplo,
fonte
setText()
e adicioná-lo novamente depois.Eu uso assim:
E toda vez que você precisar alterar o texto programaticamente, primeiro limpe o foco
fonte
Você pode usar a sintaxe DSL do Kotlin para ter a solução genérica para isso:
E dentro de seu TextWatcher, você pode usá-lo como:
fonte
Isso funciona bem para mim
fonte
O problema pode ser facilmente resolvido usando
tag
arquivado e você nem precisa lidar com o foco do editText.Definir o texto e a tag de forma programática
Verificando
tag
onTextChangedfonte
Se você precisa se concentrar na
EditText
alteração do texto, pode solicitar o foco:fonte
tente esta lógica: eu queria setText ("") sem ir para o loop infinito e este código funciona para mim. Espero que você possa modificar isso para atender às suas necessidades
fonte
Aqui está uma classe útil que fornece uma interface mais simples do que TextWatcher para o caso normal de querer ver as alterações conforme elas ocorrem. Também permite ignorar a próxima alteração conforme solicitado pelo OP.
Use-o assim:
Sempre que quiser modificar o conteúdo
editText
sem causar uma cascata de edições recursivas, faça o seguinte:fonte
Minha variante:
Defina ouvintes apenas usando setOnTextChangeListener () e defina texto apenas usando setNewText (eu queria substituir setText (), mas é o final)
fonte
Eu criei uma classe abstrata que atenua o problema cíclico de quando uma modificação no EditText é feita por meio de um TextWatcher.
fonte
Muito simples, defina o texto com este método
fonte
Você deve garantir que sua implementação de alterações de texto seja estável e não altere o texto se nenhuma alteração for necessária. Normalmente, seria qualquer conteúdo que já tenha passado pelo observador uma vez.
O erro mais comum é definir um novo texto no EditText associado ou no Editable, mesmo que o texto não tenha sido realmente alterado.
Além disso, se você fizer alterações no Editável em vez de em alguma Visualização específica, pode facilmente reutilizar seu observador e também pode testá-lo isoladamente com alguns testes de unidade para garantir que tenha o resultado desejado.
Como Editable é uma interface, você pode até usar uma implementação fictícia dela que lança uma RuntimeException se algum de seus métodos for chamado para tentar alterar seu conteúdo, ao testar um conteúdo que deve ser estável.
fonte
Minha maneira de fazer as coisas:
No segmento de gravação
O ouvinte
Funciona mesmo assim.
fonte