web-dev-qa-db-fra.com

android sur l'écouteur de modifications de texte

J'ai une situation où il y a deux champs. field1 et field2. Tout ce que je veux faire est de vider field2 lorsque field1 est modifié et inversement. Donc, à la fin, un seul champ a un contenu.

field1 = (EditText)findViewById(R.id.field1);
field2 = (EditText)findViewById(R.id.field2);

field1.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     field1.setText("");
   }
  });

Cela fonctionne bien si j'attache addTextChangedListener à field1 uniquement, mais lorsque je le fais pour les deux champs, l'application se bloque. Évidemment parce qu'ils essaient de se changer indéfiniment. Une fois que field1 change, il efface field2 à ce moment-là field2 est modifié pour effacer field1 et ainsi de suite ...

Quelqu'un peut-il suggérer une solution?

211
inrob

Vous pouvez ajouter une coche à effacer uniquement lorsque le texte du champ n'est pas vide (c'est-à-dire lorsque la longueur est différente de 0).

field1.addTextChangedListener(new TextWatcher() {

   @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(s.length() != 0)
        field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   @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(s.length() != 0)
         field1.setText("");
   }
  });

Documentation pour TextWatcherici .

Veuillez également respecter conventions de nommage .

385
user2336315

Je sais que c'est vieux, mais il est possible que quelqu'un le revienne un jour.

J'ai eu un problème similaire où j'appellerais setText sur un EditText et onTextChanged serait appelé quand je ne le voulais pas. Ma première solution consistait à écrire du code après avoir appelé setText () pour réparer les dommages causés par le programme d'écoute. Mais ce n'était pas très élégant. Après des recherches et des tests, j'ai découvert que l'utilisation de getText (). Clear () efface le texte de la même manière que setText (""), mais comme il ne définit pas le texte, l'écouteur n'est pas appelé. résolu mon problème. J'ai commuté tous mes appels setText ("") vers getText (). Clear () et je n'avais plus besoin des bandages, alors peut-être que cela résoudra également votre problème.

Essaye ça:

Field1 = (EditText)findViewById(R.id.field1);
Field2 = (EditText)findViewById(R.id.field2);

Field1.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      Field2.getText().clear();
   }
  });

Field2.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     Field1.getText().clear();
   }
  });
16
BobVicktor

Si vous utilisez Kotlin pour le développement Android, vous pouvez ajouter TextChangedListener() à l'aide du code suivant:

myTextField.addTextChangedListener(object : TextWatcher{
        override fun afterTextChanged(s: Editable?) {}

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })
8
iHulk

J'ai également fait face au même problème et continue à obtenir des exceptions complètes, et je viens avec la solution suivante.

    edt_amnt_sent.addTextChangedListener(new TextWatcher() {    
        @Override
        public void afterTextChanged(Editable s) {

            if (skipOnChange)
                return;

            skipOnChange = true;
            try {
                //method
                }
            } catch (NumberFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                skipOnChange = false;
            }
        }
    });

    edt_amnt_receive.addTextChangedListener(new TextWatcher() {


        @Override
        public void afterTextChanged(Editable s) {

            if (skipOnChange)
                return;

            skipOnChange = true;
            try 
            {
                //method
            } catch (NumberFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                skipOnChange = false;
            }
        }
    });

déclarée initialement booléenne skipOnChange = false;

5
Sumit

Un peu tard pour répondre, mais voici une solution réutilisable:

/**
 * An extension of TextWatcher which stops further callbacks being called as 
 * a result of a change happening within the callbacks themselves.
 */
public abstract class EditableTextWatcher implements TextWatcher {

    private boolean editing;

    @Override
    public final void beforeTextChanged(CharSequence s, int start, 
                                                    int count, int after) {
        if (editing)
            return;

        editing = true;
        try {
            beforeTextChange(s, start, count, after);
        } finally {
            editing = false;
        }
    }

    protected abstract void beforeTextChange(CharSequence s, int start, 
                                                     int count, int after);

    @Override
    public final void onTextChanged(CharSequence s, int start, 
                                                int before, int count) {
        if (editing)
            return;

        editing = true;
        try {
            onTextChange(s, start, before, count);
        } finally {
            editing = false;
        }
    }

    protected abstract void onTextChange(CharSequence s, int start, 
                                            int before, int count);

    @Override
    public final void afterTextChanged(Editable s) {
        if (editing)
            return;

        editing = true;
        try {
            afterTextChange(s);
        } finally {
            editing = false;
        }
    }

    public boolean isEditing() {
        return editing;
    }

    protected abstract void afterTextChange(Editable s);
}

Ainsi, lorsque ce qui précède est utilisé, aucun appel setText() ayant lieu dans TextWatcher n'entraînera plus l'appel de TextWatcher:

/**
 * A setText() call in any of the callbacks below will not result in TextWatcher being 
 * called again.
 */
public class MyTextWatcher extends EditableTextWatcher {

    @Override
    protected void beforeTextChange(CharSequence s, int start, int count, int after) {
    }

    @Override
    protected void onTextChange(CharSequence s, int start, int before, int count) {
    }

    @Override
    protected void afterTextChange(Editable s) {
    }
}
5
Eurig Jones

Vous pouvez également utiliser la méthode hasFocus ():

public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     if (Field2.hasfocus()){
         Field1.setText("");
     }
   }

Nous avons testé cela pour un travail universitaire sur lequel je travaillais et qui visait à convertir les échelles de température au fur et à mesure que l'utilisateur les saisissait. Travaillait parfaitement, et c'est beaucoup plus simple.

4
renam

cochez String avant de définir un autre EditText à vide. si Field1 est vide, pourquoi doit-il être remplacé par ("")? afin que vous puissiez vérifier la taille de votre chaîne avec s.lenght () ou toute autre solution

une autre façon de vérifier la longueur de String est la suivante:

String sUsername = Field1.getText().toString();
if (!sUsername.matches(""))
{
// do your job
}
3
Shayan Pourvatan