问题
How can I avoid that a code line like:
((EditText) findViewById(R.id.MyEditText)).setText("Hello");
Will cause an event here:
((EditText) findViewById(R.id.MyEditText)).addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// HERE
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
I want to know if there is any way to inhibit the execution of onTextChanged as I noticed in the case of selecting a AutoCompleteTextView's dropdown result (no onTextChanged is executed!).
I'm not seeking for workarounds like "if hello do nothing"...
回答1:
The Source for AutoCompleteTextView shows that they set a boolean to say the text is being replaced by the block completion
mBlockCompletion = true;
replaceText(convertSelectionToString(selectedItem));
mBlockCompletion = false;
This is as good a way as any to achieve what you want to do. The TextWatcher then checks to to see if the setText has come via a completion and returns out of the method
void doBeforeTextChanged() {
if (mBlockCompletion) return;
Adding and removing the TextWatcher will be more time consuming for the application
回答2:
You can check which View has the focus currently to distinguish between user and program triggered events.
EditText myEditText = (EditText) findViewById(R.id.myEditText);
myEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(myEditText.hasFocus()) {
// is only executed if the EditText was directly changed by the user
}
}
//...
});
Take a look here for a more detailled version of that answer.
回答3:
An alternative way to achieve this would be to use setOnKeyListener.
This will only trigger when the user presses a key rather than whenever the EditText is changed by the user OR programmatically.
myEditText.setOnKeyListener(new EditText.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch(event.getAction()) {
case KeyEvent.ACTION_DOWN:
// beforeTextChanged
break;
case KeyEvent.ACTION_UP:
// afterTextChanged
break;
}
return false;
}
});
回答4:
I don't think there is an easy way to disable the listener, but you can get around it by either:
- Removing the
TextWatcherbefore you set the text, and adding it back after. - Or set a
booleanflag before you set the text, which tells theTextWatcherto ignore it.
E.g.
boolean ignoreNextTextChange = true;
((EditText) findViewById(R.id.MyEditText)).setText("Hello");
And in your TextWatcher:
new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
/*
If the flag is set to ignore the next text change,
reset the flag, and return without doing anything.
*/
if (ignoreNextTextChange){
ignoreNextTextChange = false;
return;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
It's a little hacky, but it should work :)
回答5:
Alternatively you can simply use mEditText.hasFocus() to distinguish between Text that human-changed or program-changed, this works fine for me:
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
if (mEditText.hasFocus()) {
// Do whatever
}
}
Hope this helps!
回答6:
Only two ways I can see
- you check within the listener
- you add/remove the listener according to certain conditions
As the first way is a unwanted workaround for you I am a afraid you have work around with the second way.
来源:https://stackoverflow.com/questions/12802277/how-can-i-avoid-execution-of-ontextchanged-in-androids-edittext