Mam EditText
pole z obserwatorem tekstu klienta. W fragmencie kodu muszę zmienić wartość w EditText, którego używam .setText("whatever")
.
Problem polega na tym, że gdy tylko dokonam tej zmiany afterTextChanged
, zostanie wywołana metoda, która utworzyła nieskończoną pętlę. Jak mogę zmienić tekst bez uruchamiania go po zmianie tekstu?
Potrzebuję tekstu w metodzie afterTextChanged, więc nie sugeruj usuwania TextWatcher
.
java
android
event-handling
infinite-loop
user1143767
źródło
źródło
Krótka odpowiedź
Możesz sprawdzić, który widok ma aktualnie fokus, aby rozróżniać zdarzenia wyzwalane przez użytkownika i program.
Długa odpowiedź
Jako dodatek do krótkiej odpowiedzi: w przypadku, gdy
myEditText
już ma fokus, gdy programistycznie zmieniasz tekst, który powinieneś wywołaćclearFocus()
, dzwoniszsetText(...)
i po ponownym zażądaniu fokusu. Dobrym pomysłem byłoby umieszczenie tego w funkcji narzędzia:Kotlin:
Ponieważ Kotlin obsługuje funkcje rozszerzeń, twoja funkcja narzędziowa mogłaby wyglądać następująco:
źródło
getActivity().getCurrentFocus()
i kotlinactivity?.currentFocus
hasFocus()
bezpośrednio naEditText
.Stosowanie:
Możesz odczuwać niewielkie opóźnienie podczas szybkiego wprowadzania tekstu, jeśli używasz editText.setText () zamiast editable.replace () .
źródło
Łatwa sztuczka do naprawienia ... o ile logika wyprowadzenia nowej wartości tekstu edycji jest idempotentna (co prawdopodobnie byłoby, ale tylko mówienie). W metodzie detektora modyfikuj tekst edycji tylko wtedy, gdy bieżąca wartość jest inna niż ostatnia modyfikacja wartości.
na przykład,
źródło
setText()
i dodać go ponownie po.Używam w ten sposób:
Za każdym razem, gdy musisz programowo zmienić tekst, najpierw wyczyść fokus
źródło
Możesz użyć składni Kotlin DSL, aby uzyskać ogólne rozwiązanie:
Wewnątrz swojego TextWatchera możesz go używać jako:
źródło
To działa dobrze dla mnie
źródło
Problem można łatwo rozwiązać za pomocą
tag
pola filed i nie musisz nawet zajmować się aktywnością editText.Programowe ustawianie tekstu i tagu
Sprawdzanie
tag
w onTextChangedźródło
Jeśli chcesz skupić się na
EditText
tekście zmiany, możesz poprosić o fokus:źródło
wypróbuj tę logikę: chciałem ustawić tekst ("") bez przechodzenia do nieskończonej pętli, a ten kod działa dla mnie. Mam nadzieję, że możesz to zmodyfikować, aby pasowało do twoich wymagań
źródło
Oto przydatna klasa, która zapewnia prostszy interfejs niż TextWatcher w normalnym przypadku, gdy chcesz zobaczyć zmiany w momencie ich wystąpienia. Pozwala również na ignorowanie następnej zmiany zgodnie z żądaniem PO.
Użyj tego w ten sposób:
Jeśli chcesz zmodyfikować zawartość
editText
bez powodowania kaskady rekurencyjnych edycji, zrób to:źródło
Mój wariant:
Ustaw detektory tylko za pomocą setOnTextChangeListener () i ustaw tekst tylko za pomocą setNewText (chciałem przesłonić setText (), ale jest to ostateczne)
źródło
Stworzyłem abstrakcyjną klasę, która łagodzi cykliczny problem, gdy modyfikacja EditText jest dokonywana za pośrednictwem TextWatchera.
źródło
Bardzo prosty, ustaw tekst za pomocą tej metody
źródło
Powinieneś upewnić się, że wprowadzanie zmian w tekście jest stabilne i nie zmienia tekstu, jeśli żadna zmiana nie jest potrzebna. Zwykle byłaby to każda treść, która już raz przeszła przez obserwatora.
Najczęstszym błędem jest ustawienie nowego tekstu w powiązanym EditText lub Editable, mimo że tekst w rzeczywistości nie został zmieniony.
Ponadto, jeśli wprowadzisz zmiany w Edytowalnym zamiast w jakimś konkretnym widoku, możesz łatwo ponownie użyć swojego obserwatora, a także możesz przetestować go w izolacji za pomocą niektórych testów jednostkowych, aby upewnić się, że ma oczekiwany wynik.
Ponieważ Editable jest interfejsem, możesz nawet użyć jego fałszywej implementacji, która generuje wyjątek RuntimeException, jeśli zostanie wywołana którakolwiek z jego metod próbujących zmienić jego zawartość, podczas testowania zawartości, która powinna być stabilna.
źródło
Mój sposób na zrobienie tego:
W segmencie zapisu
Słuchacz
Działa i tak.
źródło