127 votes

Comment puis-je modifier le texte EditText sans déclencher Text Watcher ?

J'ai un EditText avec un Customer Text Watcher dessus. Dans un morceau de code, je dois modifier la valeur dans EditText, ce que je fais en utilisant .setText("whatever") .

Le problème est que dès que je fais ce changement, la afterTextChanged est appelée, ce qui crée une boucle infinie. Comment puis-je modifier le texte sans qu'il ne déclenche afterTextChanged ?

J'ai besoin du texte dans la méthode afterTextChanged, alors ne suggérez pas de supprimer le TextWatcher .

79voto

CasualT Points 2590

Vous pouvez désinscrire l'observateur, puis le réinscrire.

Alternativement, vous pouvez définir un indicateur pour que votre observateur sache quand vous venez de modifier le texte vous-même (et devrait donc l'ignorer).

46voto

Chan Chun Him Points 601

Java:

 public class MyTextWatcher implements TextWatcher {
    private EditText editText;

    // Pass the EditText instance to TextWatcher by constructor
    public MyTextWatcher(EditText editText) {
        this.editText = editText;
    }

    @Override
    public void afterTextChanged(Editable e) {
        // Unregister self before update
        editText.removeTextChangedListener(this);

        // The trick to update text smoothly.
        e.replace(0, e.length(), e.toString());

        // Re-register self after update
        editText.addTextChangedListener(this);
    }

    ...
}

Kotlin :

 class MyTextWatcher(private val editText: EditText) : TextWatcher {

  override fun afterTextChanged(e: Editable) {
    editText.removeTextChangedListener(this)
    e.replace(0, e.length, e.toString())
    editText.addTextChangedListener(this)
  }

  ...
}

Usage:

 et_text.addTextChangedListener(new MyTextWatcher(et_text));

Vous pouvez ressentir un léger décalage lors de la saisie rapide de texte si vous utilisez editText.setText() au lieu de editable.replace() .

18voto

Jeffrey Blattman Points 8891

Astuce facile à corriger ... tant que votre logique pour dériver la nouvelle valeur de texte d'édition est idempotente (ce qu'elle serait probablement, mais juste en train de dire). Dans votre méthode d'écouteur, ne modifiez le texte d'édition que si la valeur actuelle est différente de la dernière fois que vous avez modifié la valeur.

par exemple,

 TextWatcher tw = new TextWatcher() {
  private String lastValue = "";

  @Override
  public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  }

  @Override
  public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  }

  @Override
  public void afterTextChanged(Editable editable) {

    // Return value of getNewValue() must only depend
    // on the input and not previous state
    String newValue = getNewValue(editText.getText().toString());
    if (!newValue.equals(lastValue)) {
      lastValue = newValue;

      editText.setText(newValue);
    }
  }
};

8voto

Alex Misulya Points 45

Vous pouvez utiliser la syntaxe Kotlin DSL pour avoir la solution générique pour cela :

 fun TextView.applyWithDisabledTextWatcher(textWatcher: TextWatcher, codeBlock: TextView.() -> Unit) {
    this.removeTextChangedListener(textWatcher)
    codeBlock()
    this.addTextChangedListener(textWatcher)
}

Et dans votre TextWatcher, vous pouvez l'utiliser comme :

 editText.applyWithDisabledTextWatcher(this) {
    text = formField.name
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X