ich habe ein EditText
Feld mit einem Customer Text Watcher. In einem Code muss ich den Wert im EditText ändern, den ich verwende .setText("whatever")
.
Das Problem ist, sobald ich das ändere afterTextChanged
Methode aufgerufen, die eine Endlosschleife erzeugt. Wie kann ich den Text ändern, ohne dass afterTextChanged ausgelöst wird?
Ich brauche den Text in der afterTextChanged-Methode, also schlage nicht vor, den zu entfernen TextWatcher
.
java
android
event-handling
infinite-loop
user1143767
quelle
quelle
Kurze Antwort
Sie können überprüfen, welche Ansicht derzeit den Fokus hat, um zwischen benutzer- und programmgesteuerten Ereignissen zu unterscheiden.
Lange Antwort
Als Ergänzung zur kurzen Antwort: Falls
myEditText
der Fokus bereits vorhanden ist, wenn Sie den aufzurufenden Text programmgesteuert ändern, rufenclearFocus()
Sie ansetText(...)
und nachdem Sie den Fokus erneut angefordert haben. Es wäre eine gute Idee, dies in eine Utility-Funktion zu integrieren:Für Kotlin:
Da Kotlin Erweiterungsfunktionen unterstützt, könnte Ihre Utility-Funktion folgendermaßen aussehen:
quelle
getActivity().getCurrentFocus()
und Kotlinactivity?.currentFocus
hasFocus()
direkt auf der anrufenEditText
.Verwendung:
Sie können ein wenig Verzögerung fühlen , wenn die Eingabe von Text schnell , wenn Sie mit editText.setText () statt editable.replace () .
quelle
Einfacher Trick zu beheben ... solange Ihre Logik zum Ableiten des neuen Bearbeitungs-Textwerts idempotent ist (was es wahrscheinlich wäre, aber nur zu sagen). Ändern Sie in Ihrer Listener-Methode den Bearbeitungstext nur, wenn sich der aktuelle Wert von dem Wert unterscheidet, den Sie zuletzt geändert haben.
z.B,
quelle
setText()
und ihn anschließend erneut hinzuzufügen.Ich benutze diesen Weg:
Und jedes Mal, wenn Sie Text programmgesteuert ändern müssen, löschen Sie zuerst den Fokus
quelle
Sie können die Kotlin DSL-Syntax verwenden, um die generische Lösung dafür zu erhalten:
In Ihrem TextWatcher können Sie Folgendes verwenden:
quelle
Das funktioniert gut für mich
quelle
Das Problem kann einfach mit "
tag
Filed" gelöst werden , und Sie müssen sich nicht einmal mit dem Fokus von editText befassen.Programmgesteuertes Einstellen von Text und Tag
Überprüfung auf die
tag
in OnTextChangedquelle
Wenn Sie sich auf das
EditText
Ändern von Text konzentrieren müssen, können Sie den Fokus anfordern:quelle
Versuchen Sie diese Logik: Ich wollteText ("") setzen, ohne in die Endlosschleife zu gehen, und dieser Code funktioniert für mich. Ich hoffe, Sie können dies an Ihre Anforderungen anpassen
quelle
Hier ist eine praktische Klasse, die eine einfachere Oberfläche als TextWatcher bietet, wenn Sie normalerweise Änderungen sehen möchten, sobald sie auftreten. Es ermöglicht auch das Ignorieren der nächsten Änderung, wenn das OP angefordert wird.
Verwenden Sie es so:
Wenn Sie den Inhalt von ändern möchten,
editText
ohne eine Kaskade rekursiver Änderungen zu verursachen, gehen Sie folgendermaßen vor:quelle
Meine Variante:
Stellen Sie Listener nur mit setOnTextChangeListener () und Text nur mit setNewText ein (ich wollte setText () überschreiben, aber es ist endgültig)
quelle
Ich habe eine abstrakte Klasse erstellt, die das zyklische Problem verringert, wenn eine Änderung am EditText über einen TextWatcher vorgenommen wird.
quelle
Sehr einfach, setzen Sie Text mit dieser Methode
quelle
Sie sollten sicherstellen, dass Ihre Implementierung von Textänderungen stabil ist und den Text nicht ändert, wenn keine Änderung erforderlich ist. Normalerweise ist das jeder Inhalt, der den Beobachter bereits einmal durchlaufen hat.
Der häufigste Fehler besteht darin, einen neuen Text im zugehörigen EditText oder im Editable festzulegen, obwohl der Text nicht tatsächlich geändert wurde.
Wenn Sie Ihre Änderungen an der bearbeitbaren Ansicht anstelle einer bestimmten Ansicht vornehmen, können Sie Ihren Watcher außerdem problemlos wiederverwenden und ihn mit einigen Komponententests isoliert testen, um sicherzustellen, dass das gewünschte Ergebnis erzielt wird.
Da Editable eine Schnittstelle ist, können Sie sogar eine Dummy-Implementierung verwenden, die eine RuntimeException auslöst, wenn eine ihrer Methoden aufgerufen wird, die versuchen, ihren Inhalt zu ändern, wenn Sie Inhalte testen, die stabil sein sollen.
quelle
Mein Weg, das Ding zu machen:
Im Schreibsegment
Der Zuhörer
Funktioniert trotzdem.
quelle