I personally prefer automatic submit after end of typing. Here's how you can detect this event.
Declarations and initialization:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Listener in e.g. onCreate()
EditText editTextStop = (EditText) findViewById(R.id.editTextStopId);
editTextStop.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) {
if(timer != null)
timer.cancel();
}
@Override
public void afterTextChanged(final Editable s) {
//avoid triggering event when text is too short
if (s.length() >= 3) {
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
serviceConnector.getStopPoints(s.toString());
}
}, DELAY);
}
}
});
So, when text is changed the timer is starting to wait for any next changes to happen. When they occure timer is cancelled and then started once again.
I had the same issue and did not want to rely on the user pressing Done or Enter.
My first attempt was to use the onFocusChange listener, but it occurred that my EditText got the focus by default. When user pressed some other view, the onFocusChange was triggered without the user ever having assigned it the focus.
Next solution did it for me, where the onFocusChange is attached if the user touched the EditText:
final myEditText = new EditText(myContext); //make final to refer in onTouch
myEditText.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
myEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
// user is done editing
}
}
}
}
}
In my case, when the user was done editing the screen was rerendered, thereby renewing the myEditText object. If the same object is kept, you should probably remove the onFocusChange listener in onFocusChange to prevent the onFocusChange issue described at the start of this post.
Better way, you can also use EditText onFocusChange listener to check whether user has done editing: (Need not rely on user pressing the Done or Enter button on Soft keyboard)
((EditText)findViewById(R.id.youredittext)).setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) { {
// Validate youredittext
}
}
});
Note : For more than one EditText, you can also let your class implement View.OnFocusChangeListener then set the listeners to each of you EditText and validate them as below
((EditText)findViewById(R.id.edittext1)).setOnFocusChangeListener(this);
((EditText)findViewById(R.id.edittext2)).setOnFocusChangeListener(this);
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) {
switch (view.getId()) {
case R.id.edittext1:
// Validate EditText1
break;
case R.id.edittext2:
// Validate EditText2
break;
}
}
}
Although many answers do point in the right direction I think none of them answers what the author of the question was thinking about. Or at least I understood the question differently because I was looking for answer to similar problem.
The problem is "How to know when the user stops typing without him pressing a button" and trigger some action (for example auto-complete). If you want to do this start the Timer in onTextChanged with a delay that you would consider user stopped typing (for example 500-700ms), for each new letter when you start the timer cancel the earlier one (or at least use some sort of flag that when they tick they don't do anything). Here is similar code to what I have used:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
Note that I modify running boolean flag inside my async task (Task gets the json from the server for auto-complete).
Also keep in mind that this creates many timer tasks (I think they are scheduled on the same Thread thou but would have to check this), so there are probably many places to improve but this approach also works and the bottom line is that you should use a Timer since there is no "User stopped typing event"
I ended her with the same problem and I could not use the the solution with onEditorAction or onFocusChange and did not want to try the timer. A timer is too dangerous for may taste, because of all the threads and too unpredictable, as you do not know when you code is executed.
The onEditorAction do not catch when the user leave without using a button and if you use it please notice that KeyEvent can be null. The focus is unreliable at both ends the user can get focus and leave without enter any text or selecting the field and the user do not need to leave the last EditText field.
My solution use onFocusChange and a flag set when the user starts editing text and a function to get the text from the last focused view, which I call when need.
I just clear the focus on all my text fields to tricker the leave text view code, The clearFocus code is only executed if the field has focus. I call the function in onSaveInstanceState so I do not have to save the flag (mEditing) as a state of the EditText view and when important buttons is clicked and when the activity is closed.
Be careful with TexWatcher as it is call often I use the condition on focus to not react when the onRestoreInstanceState code entering text.
I
final EditText mEditTextView = (EditText) getView();
mEditTextView.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) {
}
@Override
public void afterTextChanged(Editable s) {
if (!mEditing && mEditTextView.hasFocus()) {
mEditing = true;
}
}
});
mEditTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus && mEditing) {
mEditing = false;
///Do the thing
}
}
});
protected void saveLastOpenField(){
for (EditText view:getFields()){
view.clearFocus();
}
}
I personally prefer automatic submit after end of typing. Here's how you can detect this event.
Declarations and initialization:
Listener in e.g. onCreate()
So, when text is changed the timer is starting to wait for any next changes to happen. When they occure timer is cancelled and then started once again.
I had the same issue and did not want to rely on the user pressing Done or Enter.
My first attempt was to use the onFocusChange listener, but it occurred that my EditText got the focus by default. When user pressed some other view, the onFocusChange was triggered without the user ever having assigned it the focus.
Next solution did it for me, where the onFocusChange is attached if the user touched the EditText:
In my case, when the user was done editing the screen was rerendered, thereby renewing the myEditText object. If the same object is kept, you should probably remove the onFocusChange listener in onFocusChange to prevent the onFocusChange issue described at the start of this post.
Better way, you can also use EditText onFocusChange listener to check whether user has done editing: (Need not rely on user pressing the Done or Enter button on Soft keyboard)
Note : For more than one EditText, you can also let your class implement
View.OnFocusChangeListener
then set the listeners to each of you EditText and validate them as belowAlthough many answers do point in the right direction I think none of them answers what the author of the question was thinking about. Or at least I understood the question differently because I was looking for answer to similar problem. The problem is "How to know when the user stops typing without him pressing a button" and trigger some action (for example auto-complete). If you want to do this start the Timer in onTextChanged with a delay that you would consider user stopped typing (for example 500-700ms), for each new letter when you start the timer cancel the earlier one (or at least use some sort of flag that when they tick they don't do anything). Here is similar code to what I have used:
Note that I modify running boolean flag inside my async task (Task gets the json from the server for auto-complete).
Also keep in mind that this creates many timer tasks (I think they are scheduled on the same Thread thou but would have to check this), so there are probably many places to improve but this approach also works and the bottom line is that you should use a Timer since there is no "User stopped typing event"
I ended her with the same problem and I could not use the the solution with onEditorAction or onFocusChange and did not want to try the timer. A timer is too dangerous for may taste, because of all the threads and too unpredictable, as you do not know when you code is executed.
The onEditorAction do not catch when the user leave without using a button and if you use it please notice that KeyEvent can be null. The focus is unreliable at both ends the user can get focus and leave without enter any text or selecting the field and the user do not need to leave the last EditText field.
My solution use onFocusChange and a flag set when the user starts editing text and a function to get the text from the last focused view, which I call when need.
I just clear the focus on all my text fields to tricker the leave text view code, The clearFocus code is only executed if the field has focus. I call the function in onSaveInstanceState so I do not have to save the flag (mEditing) as a state of the EditText view and when important buttons is clicked and when the activity is closed.
Be careful with TexWatcher as it is call often I use the condition on focus to not react when the onRestoreInstanceState code entering text. I
When the user has finished editing, s/he will press
Done
orEnter