How can I do something, 0.5 second after text changed in my EditText?

前端 未结 14 1113
渐次进展
渐次进展 2020-12-23 08:49

I am filtering my list using an EditText. I want to filter the list 0.5 second after user has finished typing in EditText. I used the afterTextChanged

相关标签:
14条回答
  • 2020-12-23 09:21

    Non of the above solution worked for me.

    I needed a way for TextWatcher to not fire on every character I input inside my search view and show some progress, meaning I need to access UI thread.

    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) {}
    };
    

    Removing Handler on every onTextChanged (which is called when the user inputs a new character). afterTextChanged is called after the text has been changed inside input field where we can start new Runnable, but will cancel it if user types more characters (For more info, when these callback are called, see this). If user doesn't input anymore characters, interval will pass in postDelayed and it will call work you should do with that text.

    This code will run only once per interval, not for every key user inputs. Hope it helps someone in the future.

    0 讨论(0)
  • 2020-12-23 09:27

    Using timer for your case is not the best solution because of creating new object everytime. According to Timer documentation(http://developer.android.com/reference/java/util/Timer.html) it's better to use ScheduledThreadPoolExecutor -

    "Timers schedule one-shot or recurring tasks for execution. Prefer ScheduledThreadPoolExecutor for new code."

    Here is better approach

    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
            }
        }
    );
    
    0 讨论(0)
  • 2020-12-23 09:28

    You can use EditorActionListener for that purpose.

    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;
        }
    });
    
    0 讨论(0)
  • 2020-12-23 09:30

    With Kotlin extension functions and coroutines:

    fun AppCompatEditText.afterTextChangedDebounce(delayMillis: Long, input: (String) -> Unit) {
    var lastInput = ""
    var debounceJob: Job? = null
    val uiScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
    this.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(editable: Editable?) {
            if (editable != null) {
                val newtInput = editable.toString()
                debounceJob?.cancel()
                if (lastInput != newtInput) {
                    lastInput = newtInput
                    debounceJob = uiScope.launch {
                        delay(delayMillis)
                        if (lastInput == newtInput) {
                            input(newtInput)
                        }
                    }
                }
            }
        }
    
        override fun beforeTextChanged(cs: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(cs: CharSequence?, start: Int, before: Int, count: Int) {}
    })}
    
    0 讨论(0)
  • 2020-12-23 09:30

    How do you determine that they have finished writing? That the edittext loses focus? Then there is setOnFocusChangedListener.

    Responding to latest edit in question: If you want to wait a specific time after the latest key stroke, then you have to start up a thread at the first keypress (use TextWatcher). Constantly register the time of the latest key stroke. Let the thread sleep to the the time of the latest keystroke + 0.5 seconds. If the timestamp of the latest keystroke has not been updated, do whatever you had intended.

    0 讨论(0)
  • 2020-12-23 09:31

    that is the event while and after finish of typing ... add a textWatcher and in the onTextChanged method put :

    if (charSequence.length() > 0){// your code }

    0 讨论(0)
提交回复
热议问题