J'ai un problème ennuyeux avec TextWatcher. J'ai cherché sur le Web mais je n'ai rien trouvé. apprécier si quelqu'un pouvait m'aider.
Pour une raison quelconque, les appels aux événements TextWatcher lors d'un changement de texte sont irréguliers. parfois ils sont déclenchés une fois (comme ils devraient l'être), parfois deux fois, et parfois 3 fois. ne sais pas pourquoi, le tout est très simple. parfois, le paramètre Editable sur afterTextChanged () renvoie des valeurs vides dans toString () et length ().
le code est ci-dessous:
private TextWatcher mSearchAddressTextChangeListener = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void afterTextChanged(Editable searchedAddress) {
System.out.println("called multiple times.");
}
};
à l'intérieur de afterTextChanged()
(et la AsyncTask
) je ne modifie pas le texte ou la vue EditText
.
j'ai vu la question posée dans les événements de TextWatcher sont appelés deux fois , mais je fais déclencher les événements plus (ou moins) plus de deux fois.
de toute façon, appréciez toute aide.
EDIT: J'ai supprimé le contenu de afterTextChanged () car ce problème se produit même sans mon code. ce qui me fait croire que c'est un bug. Le bogue se produit lorsqu'un caractère `` espace '' est entré juste après un caractère normal (les gestionnaires d'événements sont déclenchés deux fois) ou lorsqu'un caractère `` espace '' après la suppression d'un caractère normal (retour arrière. Les gestionnaires d'événements sont déclenchés 3 fois). l'aide sera toujours appréciée.
J'ai eu le même genre de problème, lorsque j'ai appuyé sur la touche retour arrière avec le curseur à la fin d'un texte continu, afterTextChange a été appelé 3 fois: - La première fois avec la valeur s correcte - La deuxième fois avec une valeur claire - La troisième fois avec la valeur correcte à nouveau
Après avoir beaucoup cherché sur le Web, j'ai essayé de changer mon InputType EditText en
Android:inputType="textNoSuggestions"
Ne me demandez pas pourquoi, mais cela a fonctionné, afterTextChanged n'est désormais appelé qu'une seule fois.
Selon les pages de développeur pour TextWatcher , si une modification est apportée au Editable
dans TextWatcher
, cela déclenchera d'autres appels à tous les TextWatchers
lié à ce Editable
. Maintenant, clairement votre code ne déclenche pas ce comportement.
Cependant, il est fort possible que si, pour une raison quelconque, le système a un TextWatcher
sur le Editable
, la situation que vous décrivez peut se produire. "Pourquoi", je vous entends pleurer, "cela devrait-il arriver?"
Tout d'abord, la défense classique: il n'y a aucune raison pour que cela ne se produise pas et, strictement, le code de l'application doit être écrit pour y résister.
Deuxièmement, je ne peux pas le prouver, mais je pourrais bien imaginer que le code qui gère la mise en page du texte affiché dans un EditText
utilise un TextWatcher
pour gérer la mise à jour de l'affichage du texte sur le écran. Ce code peut insérer des codes de contrôle (qui ne vous sont pas affichés) dans le Editable
pour garantir de bons sauts de ligne, etc. Il peut même faire plusieurs fois le tour d'une boucle pour bien faire les choses, et vous pourriez ne recevoir votre premier appel qu'après avoir effectué toutes ses ...
ÉDITER
Selon le commentaire de @Learn OpenGL ES, l'appel d'un TextWatcher serait normal pour des choses comme la correction automatique.
boolean isOnTextChanged = false;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
isOnTextChanged = true;
}
@Override
public void afterTextChanged(Editable quantity) {
if (isOnTextChanged) {
isOnTextChanged = false;
//dosomething
}
J'ai essayé toutes les réponses à cette question, aucune d'entre elles n'a fonctionné pour moi. Mais après quelques recherches, j'ai trouvé this post. Utiliser le RxJava pour faire le debounce a bien fonctionné pour moi. Voici ma solution finale:
Ajoutez les dépendances RxJava dans le fichier Gradle:
compile 'io.reactivex:rxandroid:1.0.1'
compile 'io.reactivex:rxjava:1.0.14'
compile 'com.artemzin.rxjava:proguard-rules:1.0.14.2'
Implémentez votre sujet:
PublishSubject<String> yourSubject = PublishSubject.create();
yourSubject .debounce(100, TimeUnit.MILLISECONDS)
.onBackpressureLatest()
.subscribe(s -> {
//Implements anything you want
});
Utilisez votre sujet dans votre TextWatcher:
TextWatcher myTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
yourSubject.onNext(s.toString()); //apply here your subject
}
@Override
public void afterTextChanged(Editable s) {
}
};
Ajoutez le TextWatcher dans l'écouteur EditText:
my_edit_text.addTextChangedListener(myTextWatcher);
vous pouvez utiliser une vérification booléenne, comme:
inputBoxNumberEt.addTextChangedListener(new TextWatcher() {
boolean ignoreChange = false;
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (!ignoreChange) {
///Do your checks
ignoreChange = true;
inputBoxNumberEt.setText(string);
inputBoxNumberEt.setSelection(inputBoxNumberEt.getText().length());
ignoreChange = false;
}
}
});
Pour moi, le code ci-dessous a fonctionné. Veuillez noter que la valeur booléenne a été modifiée après if boucle de condition dans la méthode afterTextChanged
edittext.addTextChangedListener(new TextWatcher()
{
boolean considerChange = false;
public void beforeTextChanged(CharSequence cs, int start, int count, int after) {}
public void onTextChanged(CharSequence cs, int start, int before, int count) {}
public void afterTextChanged(Editable editable)
{
if (considerChange)
{
// your code here
}
considerChange = !considerChange; //see that boolean value is being changed after if loop
}
});
Mon problème était lié à cela car j'exécutais mon application dans un émulateur et tapais sur le clavier de l'ordinateur portable ( sans utiliser celui de l'émulateur ) et l'étrange l'entrée serait dupliquée.
Cela ne s'est pas produit dans un appareil physique.
Suite à l'inspiration de Nico's réponse ci-dessus, c'est ce qui a fonctionné pour moi pour que le texte d'entrée modifié ne soit déclenché qu'une seule fois.
Ajout de la configuration de type d'entrée suivante:
1) À travers un style
<!-- in a style -->
<style name="My.Text.Style">
<item name="Android:inputType">text|textMultiLine|textVisiblePassword</item>
</style>
puis utilisé en xml comme:
<EditText
Android:id="@+id/my_edit_text"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
style="@style/My.Text.Style"
/>
[~ # ~] ou [~ # ~]
2) Directement dans le xml
<EditText
Android:id="@+id/my_edit_text"
Android:inputType="text|textMultiLine|textVisiblePassword"
/>
Les deux façons de le faire devraient être bien, le style était juste pour le cas où l'on veut le réutiliser sur d'autres écrans.