【问题标题】:How can I avoid execution of onTextChanged in Android's EditText如何避免在 Android EditText 中执行 onTextChanged
【发布时间】:2012-09-29 22:00:21
【问题描述】:

我怎样才能避免这样的代码行:

((EditText) findViewById(R.id.MyEditText)).setText("Hello");

将在此处引发事件:

((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) {
}
});

我想知道是否有任何方法可以抑制 onTextChanged 的​​执行,正如我在选择 AutoCompleteTextView 的下拉结果的情况下注意到的那样(没有执行 onTextChanged!)。

我不是在寻找诸如“如果你好,什么都不做”之类的解决方法......

【问题讨论】:

标签: android android-edittext


【解决方案1】:

您可以检查当前哪个 View 具有焦点,以区分用户和程序触发的事件。

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
        }
    }

    //...
});

查看here 以获得该答案的更详细版本。

【讨论】:

  • 很好的解决方案,我的问题没想到。
【解决方案2】:

或者,您可以简单地使用mEditText.hasFocus() 来区分人为更改或程序更改的文本,这对我来说很好:

@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
    if (mEditText.hasFocus()) {
        // Do whatever
    }
}

希望这会有所帮助!

【讨论】:

  • 我看不出它有什么帮助
【解决方案3】:

我认为没有一种简单的方法可以禁用监听器,但您可以通过以下任一方式绕过它:

  • 在设置文本之前删除TextWatcher,然后再添加回来。
  • 或者在设置文本之前设置一个boolean 标志,告诉TextWatcher 忽略它。

例如

boolean ignoreNextTextChange = true;
((EditText) findViewById(R.id.MyEditText)).setText("Hello");

在你的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) {

    }
});

这有点hacky,但它应该可以工作:)

【讨论】:

  • 返回那里是否会阻止文本更改前后的执行,或者您需要在那里进行另一个布尔检查?
【解决方案4】:

实现此目的的另一种方法是使用setOnKeyListener

这只会在用户按下某个键时触发,而不是在用户或以编程方式更改 EditText 时触发。

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;
    }
});

【讨论】:

  • 有趣的想法,但它会捕捉到用户将文本粘贴到字段中所做的文本更改吗?
  • 用户倾向于绕过按钮,直接点击离开或进入下一个单元格。
【解决方案5】:

我只能看到两种方式

  • 你在监听器中检查
  • 您根据特定条件添加/删除监听器

由于第一种方法对您来说是一种不需要的解决方法,我担心您已经使用第二种方法解决了。

【讨论】:

    【解决方案6】:

    AutoCompleteTextView 的来源表明他们设置了一个布尔值来表示文本正在被块完成替换

             mBlockCompletion = true;
             replaceText(convertSelectionToString(selectedItem));
             mBlockCompletion = false;    
    

    这是实现您想要做的任何事情的好方法。 TextWatcher 然后检查 setText 是否通过完成来完成并从方法中返回

     void doBeforeTextChanged() {
         if (mBlockCompletion) return;
    

    添加和删除 TextWatcher 对应用程序来说会更耗时

    【讨论】:

    • 我尝试编辑这个问题,但显然编辑队列已满。长话短说,如果您使用的是AutoCompleteTextView,则可以调用setText(CharSequence text, boolean filter),并将filter 传递为false,您将避免触发TextWatcher
    猜你喜欢
    • 2020-06-23
    • 2016-02-16
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多