Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if users stop typing in EditText android

I have an EditText field in my layout. I want to perform an action when the user stops typing in that edittext field. I have implemented TextWatcher and use its functions

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


@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { } 

@Override
    public void afterTextChanged(Editable editable) {

    }

The function onTextChanged and afterTextChanged get called just after typing any character, but I want to perform action after the user has finished typing in that edittext field, just like facebook does on it's "Check In" page.

How can I implement this?

like image 252
Prithniraj Nicyone Avatar asked Feb 05 '16 12:02

Prithniraj Nicyone


3 Answers

This is how I did and works for me!

long delay = 1000; // 1 seconds after user stops typing
long last_text_edit = 0;
Handler handler = new Handler();

private Runnable input_finish_checker = new Runnable() {
    public void run() {
        if (System.currentTimeMillis() > (last_text_edit + delay - 500)) {
            // TODO: do what you need here
            // ............
            // ............
            DoStuff();
        }
    }
};

EditText editText = (EditText) findViewById(R.id.editTextStopId);
editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged (CharSequence s,int start, int count,
    int after){
    }
    @Override
    public void onTextChanged ( final CharSequence s, int start, int before,
    int count){
        //You need to remove this to run only once
        handler.removeCallbacks(input_finish_checker);

    }
    @Override
    public void afterTextChanged ( final Editable s){
        //avoid triggering event when text is empty
        if (s.length() > 0) {
            last_text_edit = System.currentTimeMillis();
            handler.postDelayed(input_finish_checker, delay);
        } else {

        }
    }
}

);
like image 65
ThetNaing Mizo Avatar answered Nov 16 '22 02:11

ThetNaing Mizo


There is a very simple and easy way of doing this using RxBindings for Android,

Get the library if you haven't already,

compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'

Add and modify this snippet to your needs,

RxTextView.textChanges(mEditText)
            .debounce(3, TimeUnit.SECONDS)
            .subscribe(textChanged -> {
                Log.d("TAG", "Stopped typing!");
            });

What is Debounce Operator? - Learn more about it here

In our context, debounce will only notify you of the text change inside the EditText after a certain time has passed from the last text change that occurred inside the EditText.

Here I am waiting for 3 seconds until the last text change happened to conclude that the user has stopped typing. You can modify it according to your needs.

like image 24
Rahul Chowdhury Avatar answered Nov 16 '22 02:11

Rahul Chowdhury


If you use Kotlin, use this extension function:

fun TextView.afterTextChangedDelayed(afterTextChanged: (String) -> Unit) {
    this.addTextChangedListener(object : TextWatcher {
        var timer: CountDownTimer? = null

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}

        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}

        override fun afterTextChanged(editable: Editable?) {
            timer?.cancel()
            timer = object : CountDownTimer(1000, 1500) {
                override fun onTick(millisUntilFinished: Long) {}
                override fun onFinish() { 
                    afterTextChanged.invoke(editable.toString()) 
                }
            }.start()
        }
    })
}

Use example:

editTextPassword.afterTextChangedDelayed {
    registerViewModel.addUserPassword(it)
}
like image 21
Emmanuel Guther Avatar answered Nov 16 '22 04:11

Emmanuel Guther