¿Cómo puedo hacer algo, 0.5 segundo después de que el texto cambió en mi EditText?
Estoy filtrando mi lista usando un EditText. Quiero filtrar la lista 0.5 segundos después de que el usuario haya terminado de escribir en EditText . Utilicé el evento TextWatcher
de TextWatcher
para este propósito. Pero este evento aumenta para cada cambio de carácter en EditText.
¿Que debería hacer?
- TextWatcher.afterTextChanged tiene cadena incorrecta después de retroceso
- Android stackoverflow utilizando while loop
- Espaciado de letras en EditText para Android
- ¿Cómo utilizar Single TextWatcher para múltiples EditTexts?
- Android Manejo de muchos campos de EditText en un ListView
- Cómo enmascarar un EditText para mostrar el formato de fecha dd / mm / aaaa
- Cómo limitar el texto en números sólo de 0-59 en Editar texto en Android?
- TextWatcher llamado incluso si se establece el texto antes de agregar el observador
- Diferencias entre TextWatcher 's onTextChanged, beforeTextChanged y afterTextChanged
- Clickable compuesto drawable en EditText que hace estallar una vista en tecleo
- Android-Editext cambio después de cada cambio
- Necesita ayuda para que un TextWatcher de Android funcione con datos de código de barras compuesto entrantes
- ¿Cómo utilizo AsYouTypeFormatter TextWatcher en la aplicación de Android?
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 ); } } );
El truco está en cancelar y volver a programar Timer
cada vez, cuando el texto en EditText
consigue cambiado. ¡Buena suerte!
Utilice mejor el manejador con el método postDelayed (). En la implementación de Android, Timer creará un nuevo subproceso cada vez para ejecutar la tarea. Handler sin embargo tiene su propio Looper que se puede conectar a cualquier hilo que deseamos, por lo que no pagaremos un costo adicional para crear hilo.
Ejemplo
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) { // }
También puede utilizar la interfaz TextWatcher y crear su clase personalizada que lo implementa para volver a utilizar muchas veces su CustomTextWatcher y también puede pasar vistas o lo que sea necesario para su constructor:
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
}
Ahora en tu actividad puedes usarlo así:
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 } });
¿Cómo determinas que han terminado de escribir? ¿Que el edittext pierde el foco? Luego hay setOnFocusChangedListener .
Respuesta a la última edición en cuestión : Si desea esperar un tiempo específico después del último trazo de tecla, debe iniciar un hilo en la primera pulsación de tecla (use TextWatcher). Registre constantemente la hora de la última pulsación de tecla. Deje que el hilo duerma a la hora de la última pulsación de tecla + 0,5 segundos. Si la marca de tiempo de la última pulsación de tecla no se ha actualizado, haga lo que usted había previsto.
No de la solución anterior funcionó para mí.
Necesitaba una manera para que TextWatcher no se disparara en cada personaje que ingrese dentro de mi vista de búsqueda y muestre algún progreso, lo que significa que necesito acceder al subproceso de 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) {} };
Eliminación de Handler en cada onTextChanged (que se llama cuando el usuario introduce un nuevo carácter). AfterTextChanged se llama después de que el texto se ha cambiado dentro del campo de entrada donde podemos iniciar el nuevo Runnable, pero lo cancelará si el usuario escribe más caracteres (Para más información, cuando se llamen estos llamados, vea esto ). Si el usuario no ingresa más caracteres, el intervalo pasará en postDelayed y llamará al trabajo que debe hacer con ese texto.
Este código se ejecutará sólo una vez por intervalo, no para cada entrada de usuario clave. Espero que ayude a alguien en el futuro.
Puede utilizar EditorActionListener
para ese propósito.
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; } });
Usar temporizador para su caso no es la mejor solución debido a la creación de nuevo objeto cada vez. De acuerdo con la documentación Timer ( http://developer.android.com/reference/java/util/Timer.html ) es mejor utilizar ScheduledThreadPoolExecutor –
"Los temporizadores programan tareas de un solo disparo o recurrentes para su ejecución. Prefieren ScheduledThreadPoolExecutor para el nuevo código."
Aquí hay un mejor enfoque
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 } } );