Comment puis-je faire quelque chose, 0.5 secondes après que le texte a changé dans mon EditText?

Je filtre ma liste en utilisant EditText. Je souhaite filtrer la liste 0,5 seconde après que l'utilisateur ait fini de taper dans EditText . J'ai utilisé l'événement TextWatcher de TextWatcher à cette fin. Mais cet événement augmente pour chaque personnage change dans EditText.

Que devrais-je faire?

  • Clavier dur Fail to focus editText
  • Comment détecter la marche avec un accéléromètre Android
  • Android: TextInputLayout ne centra pas l'indice
  • Action d'intention pour les événements réseau dans android sdk
  • Android EditText setText ne met pas à jour le texte
  • Validation sur Edit Text
  • 7 Solutions collect form web for “Comment puis-je faire quelque chose, 0.5 secondes après que le texte a changé dans mon EditText?”

     editText.addTextChangedListener( 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) { } private Timer timer=new Timer(); private final long DELAY = 500; // milliseconds @Override public void afterTextChanged(final Editable s) { timer.cancel(); timer = new Timer(); timer.schedule( new TimerTask() { @Override public void run() { // TODO: do what you need here (refresh list) // you will probably need to use runOnUiThread(Runnable action) for some specific actions } }, DELAY ); } } ); 

    L'astuce consiste à annuler et à ré-programmer Timer chaque fois, lorsque le texte dans EditText est modifié. Bonne chance!

    Mieux utiliser Handler avec postDelayed (). Dans la mise en œuvre d'Android, Timer créera de nouveaux threads à chaque fois pour exécuter la tâche. Handler a cependant son propre Looper qui peut être attaché à n'importe quel fil que nous souhaitons, donc nous ne paierons pas de frais supplémentaires pour créer un thread.

    Exemple

      Handler handler = new Handler(Looper.getMainLooper() /*UI thread*/); Runnable workRunnable; @Override public void afterTextChanged(Editable s) { handler.removeCallbacks(workRunnable); workRunnable = () -> doSmth(s.toString()); handler.postDelayed(workRunnable, 500 /*delay*/); } private final void doSmth(String str) { // } 

    Vous pouvez également utiliser l'interface TextWatcher et créer votre classe personnalisée qui l'implémente pour réutiliser plusieurs fois votre CustomTextWatcher et vous pouvez également passer des vues ou tout ce dont vous avez besoin pour son constructeur:

     public abstract class CustomTextWatcherimplements TextWatcher { //Notice abstract class so we leave abstract method textWasChanged() for implementing class to define it private final TextView myTextView; //Remember EditText is a TextView so this works for EditText also public AddressTextWatcher(TextView tView) { //Notice I'm passing a view at the constructor, but you can pass other variables or whatever you need myTextView= tView; } private Timer timer = new Timer(); private final int DELAY = 500; //milliseconds of delay for timer @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(final Editable s) { timer.cancel(); timer = new Timer(); timer.schedule( new TimerTask() { @Override public void run() { textWasChanged(); } }, DELAY ); } public abstract void textWasChanged(); //Notice abstract method to leave implementation to implementing class 

    }

    Maintenant, dans votre activité, vous pouvez l'utiliser comme suit:

      myEditText.addTextChangedListener(new CustomTextWatcher(myEditText) { //Notice I'm passing in constructor of CustomTextWatcher myEditText I needed to use @Override public void textWasChanged() { //doSomething(); this is method inside your activity } }); 

    Comment déterminez-vous qu'ils ont fini d'écrire? Que l'edittext perd son focus? Ensuite, il existe setOnFocusChangedListener .

    Répondre à la dernière modification en question : si vous souhaitez attendre un moment précis après le dernier coup de touche, vous devez démarrer un thread lors de la première pression de touche (utilisez TextWatcher). Enregistrez-vous constamment l'heure du dernier coup de touche. Laissez le fil dur jusqu'à l'heure de la dernière frappe + 0,5 seconde. Si l'horodatage de la dernière frappe n'a pas été mis à jour, faites ce que vous aviez prévu.

    Non de la solution ci-dessus a fonctionné pour moi.

    J'avais besoin d'un moyen pour que TextWatcher ne déclenche pas sur tous les caractères que j'ai entrés dans ma vue de recherche et mes progrès, ce qui signifie que je dois accéder au thread UI.

     private final TextWatcher textWatcherSearchListener = new TextWatcher() { final android.os.Handler handler = new android.os.Handler(); Runnable runnable; public void onTextChanged(final CharSequence s, int start, final int before, int count) { handler.removeCallbacks(runnable); } @Override public void afterTextChanged(final Editable s) { //show some progress, because you can access UI here runnable = new Runnable() { @Override public void run() { //do some work with s.toString() } }; handler.postDelayed(runnable, 500); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} }; 

    Retrait du gestionnaire sur chaque onTextChanged (qui s'appelle lorsque l'utilisateur entre un nouveau caractère). AfterTextChanged est appelé après que le texte a été changé dans le champ de saisie où nous pouvons démarrer le nouveau Runnable, mais l'annuler si l'utilisateur tape plus de caractères (pour plus d'informations, lorsque ces rappels sont appelés, voir ceci ). Si l'utilisateur n'inscrit plus de caractères, l'intervalle passe dans PostDelayed et il appellera le travail que vous devriez faire avec ce texte.

    Ce code ne fonctionnera qu'une fois par intervalle, pas pour chaque entrée utilisateur clé. J'espère que cela aidera quelqu'un dans le futur.

    Vous pouvez utiliser EditorActionListener à cette fin.

     editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { //Do something here return true; } return false; } }); 

    L'utilisation de la minuterie pour votre cas n'est pas la meilleure solution en raison de la création d'un nouvel objet à chaque fois. Selon la documentation de Timer ( http://developer.android.com/reference/java/util/Timer.html ), il est préférable d'utiliser ScheduledThreadPoolExecutor –

    "Les horlogers programment des tâches uniques ou récurrentes pour l'exécution. Prévoyez ScheduledThreadPoolExecutor pour le nouveau code."

    Voici une meilleure approche

     Runnable runnabledelayedTask = new Runnable(){ @Override public void run(){ //TODO perform any operation here } }; editText.addTextChangedListener( 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) { } private final long DELAY = 500; // milliseconds @Override public void afterTextChanged(final Editable s) { ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(1); ScheduledFuture sf = scheduledPool.schedule(callabledelayedTask, DELAY, TimeUnit.MILLISECONDS); //you can cancel ScheduledFuture when needed } } ); 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.