How can I avoid execution of onTextChanged in Andr

2019-04-03 07:23发布

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"...

6条回答
别忘想泡老子
2楼-- · 2019-04-03 07:25

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.

查看更多
The star\"
3楼-- · 2019-04-03 07:32

I don't think there is an easy way to disable the listener, but you can get around it by either:

  • Removing the TextWatcher before you set the text, and adding it back after.
  • Or set a boolean flag before you set the text, which tells the TextWatcher to 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 :)

查看更多
成全新的幸福
4楼-- · 2019-04-03 07:35

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

查看更多
Fickle 薄情
5楼-- · 2019-04-03 07:46

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(getCurrentFocus() == myEditText) {
            // is only executed if the EditText was directly changed by the user
        }
    }

    //...
});
查看更多
家丑人穷心不美
6楼-- · 2019-04-03 07:47

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;
    }
});
查看更多
▲ chillily
7楼-- · 2019-04-03 07:50

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!

查看更多
登录 后发表回答