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

前端 未结 14 1115
渐次进展
渐次进展 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:32
    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 = 1000; // 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 (e.g. manipulating views)
                        }
                    }, 
                    DELAY
                );
            }
        }
    );
    

    The trick is in canceling and re-scheduling Timer each time, when text in EditText gets changed. Good luck!

    UPDATE For those interested in how long to set the delay, see this post.

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

    If you want to skip textWatcher for the first time only then add following code: This will allow textWatcher make any change from the second time.

        Boolean firstchange=false;
        profileEmailEditText.addTextChangedListener(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) {
                        if (firstchange) {
                            emailAlertText.setVisibility(View.VISIBLE);
                        }
                        else {
                            firstchange=true;
                        }
                    }
    
                    @Override
                    public void afterTextChanged(Editable s) {
    
                    }
                });
    
    0 讨论(0)
  • 2020-12-23 09:36

    You can use timer, after typing the text it will wait for 600 ms. Put the code inside afterTextChanged() by using delay of 600 ms.

    @Override
        public void afterTextChanged(Editable arg0) {
            // user typed: start the timer
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    // do your actual work here
                   editText.setText(et.getText().toString());
    
                }
            }, 600); // 600ms delay before the timer executes the „run“ method from TimerTask
        }
    
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // nothing to do here
        }
    
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // user is typing: reset already started timer (if existing)
            if (timer != null) {
                timer.cancel();
            }
        }
    };
    
    0 讨论(0)
  • 2020-12-23 09:37

    In Kotlin Language you can do like this

    tv_search.addTextChangedListener(mTextWatcher)
    
    private val mTextWatcher: TextWatcher = object : TextWatcher {
            private var timer = Timer()
            private val DELAY: Long = 1000L
    
            override fun afterTextChanged(s: Editable?) {
                timer.cancel()
                timer = Timer()
                timer.schedule(object : TimerTask() {
                    override fun run() {
                             //DO YOUR STUFF HERE
                    }
                }, DELAY)
            }
    
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }
    
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }
    
        }
    
    0 讨论(0)
  • 2020-12-23 09:45

    Better use Handler with postDelayed() method. In the android's implementation Timer will create new thread each time to run the task. Handler however has its own Looper that can be attached to whatever thread we wish, so we won't pay extra cost to create thread.

    Example

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

    You can use RxBindings, it's the best solution. See guide to RxJava operator debounce, I'm sure that will do great in your case.

    RxTextView.textChanges(editTextVariableName)
                .debounce(500, TimeUnit.MILLISECONDS)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String value) {
                        // do some work with the updated text
                    }
                });
    

    http://reactivex.io/documentation/operators/debounce.html

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