Android EditText OnChange监听器

141

我对 TextWatcher 有一些了解,但它会在输入每个字符时触发。我想要一个在用户完成编辑时触发的监听器。这可行吗?此外,在 TextWatcher 中,我得到了一个 Editable 的实例,但我需要一个 EditText 的实例。如何获得?

编辑:第二个问题更重要。请回答它。


2
尝试添加焦点监听器,当EditText获得焦点时,表示用户开始编辑它,而当EditText失去焦点时,表示编辑已完成。 - Houcine
https://github.com/henrychuangtw/AutoInsertEditText - HenryChuang
10个回答

257
首先,您可以在EditText失去焦点或用户按下完成按钮后查看用户是否完成了文本编辑(这取决于您的实现以及哪种方式最适合您)。
第二,如果您已将EditText声明为实例对象,则无法仅在TextWatcher中获取EditText实例。虽然不应在TextWatcher内修改EditText,因为这是不安全的。 编辑: 要能够在TextWatcher实现中获取EditText实例,可以尝试以下方法:
public class YourClass extends Activity {

    private EditText yourEditText;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        yourEditText = (EditText) findViewById(R.id.yourEditTextId);

        yourEditText.addTextChangedListener(new TextWatcher() {

            public void afterTextChanged(Editable s) {

                // you can call or do what you want with your EditText here

                // yourEditText... 
            }

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

            public void onTextChanged(CharSequence s, int start, int before, int count) {}
        });
    }
}

请注意,上述示例可能存在一些错误,但我只是想向您展示一个例子。


38

实现监听所有EditText字段时,我发现必须使用丑陋冗长的代码,这让我很困扰,因此我编写了下面的类。可能对任何遇到此问题的人有用。

public abstract class TextChangedListener<T> implements TextWatcher {
    private T target;

    public TextChangedListener(T target) {
        this.target = target;
    }

    @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) {
        this.onTextChanged(target, s);
    }

    public abstract void onTextChanged(T target, Editable s);
}

现在实现监听器的方式更加简洁。
editText.addTextChangedListener(new TextChangedListener<EditText>(editText) {
            @Override
            public void onTextChanged(EditText target, Editable s) {
                //Do stuff
            }
        });

关于它的触发频率,可以在给定的a后实现一个检查,在//Do stuff中运行所需的代码。

4
这对我非常有效,节省了很多代码行!你真是个天才! - huypham99

12

使用 ButterKnife 的任何人。你可以这样使用:

@OnTextChanged(R.id.zip_code)
void onZipCodeTextChanged(CharSequence zipCode, int start, int count, int after) {

}

8
我已经使用 AutotextView 完成了它:
AutotextView textView = (AutotextView) findViewById(R.id.autotextview);
textView.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
        seq = cs;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int arg1, int arg2, int arg3) {

    }

    @Override
    public void afterTextChanged(Editable arg0) {
        new SearchTask().execute(seq.toString().trim());
    }

});

3
 myTextBox.addTextChangedListener(new TextWatcher() {  

    public void afterTextChanged(Editable s) {}  

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

    public void onTextChanged(CharSequence s, int start, int before, int count) {  

    TextView myOutputBox = (TextView) findViewById(R.id.myOutputBox);  
    myOutputBox.setText(s);  

    }  
});  

2
代码末尾有一个不必要的 }。 - Howard

2

TextWatcher 对我来说无法正常工作,因为它会对每个 EditText 进行触发并混淆彼此的值。

这是我的解决方案:

public class ConsultantTSView extends Activity {
    .....

    //Submit is called when I push submit button.
    //I wanted to retrieve all EditText(tsHours) values in my HoursList

    public void submit(View view){

        ListView TSDateListView = (ListView) findViewById(R.id.hoursList);
        String value = ((EditText) TSDateListView.getChildAt(0).findViewById(R.id.tsHours)).getText().toString();
    }
}

因此,通过使用 getChildAt(xx) 方法,您可以检索 ListView 中的任何项目,并使用 findViewById 获取单个项目。然后它将给出最近的值。

1

就我所知,只有两种方法可以做到。你如何知道用户已经完成了一个单词的输入?要么是在失去焦点时,要么是点击“确定”按钮。在我看来,你无法知道用户按下了最后一个字符...

因此,请调用onFocusChange(View v, boolean hasFocus)或添加一个按钮和单击侦听器。


1
在 Kotlin Android 中,使用以下代码设置 EditText 监听器:

   val searchTo : EditText = findViewById(R.id.searchTo)
   searchTo.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(s: Editable) {

        // you can call or do what you want with your EditText here

        // yourEditText...
    }

    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
})

1
每输入一个字符,Watcher方法都会触发。所以,我基于onFocusChange方法编写了此代码:
public static boolean comS(String s1,String s2){
    if (s1.length()==s2.length()){
        int l=s1.length();
        for (int i=0;i<l;i++){
            if (s1.charAt(i)!=s2.charAt(i))return false;
        }
        return true;
    }
    return false;
}

public void onChange(final EditText EdTe, final Runnable FRun){
    class finalS{String s="";}
    final finalS dat=new finalS();  
    EdTe.setOnFocusChangeListener(new OnFocusChangeListener() {          
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {dat.s=""+EdTe.getText();}
            else if (!comS(dat.s,""+EdTe.getText())){(new Handler()).post(FRun);}       
        }
    });
}

要使用它,只需像这样调用:
onChange(YourEditText, new Runnable(){public void run(){
    // V  V    YOUR WORK HERE

    }}
);

你可以通过使用!equal函数替换!comS(dat.s,""+EdTe.getText())来忽略comS函数。然而,equal函数本身有时在运行时无法正确工作。
当用户聚焦输入时,onChange监听器会记住EditText的旧数据,然后在用户失去焦点或跳转到其他输入时比较新数据。如果比较旧字符串与新字符串不同,则触发工作。
如果你只有一个EditText,那么你需要制作一个ClearFocus函数,通过在窗口外部创建一个终极秘密透明微型EditText,并将焦点请求到它上面,然后通过Import Method Manager隐藏键盘。

0

我已经采用了 @RNGuy 的解决方案,感谢他!并且稍微更改了监听器,现在它只会通过更新 textView 来接受整数。

import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

public abstract class NumberChangedListener implements TextWatcher {
    private final EditText target;
    private final String defaultValue;

    public NumberChangedListener(EditText target, int defaultValue) {
        this.target = target;
        this.defaultValue = defaultValue + "";
    }

    @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) {
        this.onTextChanged(target, s);
    }

    private void onTextChanged(EditText target, Editable s) {
        String input = s.toString();
        String number = input.replaceAll("[^\\d]", "");

        if (!number.equals(input)) {
            target.setText(number);
            return;
        }

        Integer integer;

        try {
            integer = Integer.valueOf(number);
        } catch (NumberFormatException ignored) {
            target.setText(defaultValue);
            return;
        }

        if (!integer.toString().equals(number)) {
            target.setText(integer.toString());
            return;
        }

        onNumberChanged(integer);

    }

    public abstract void onNumberChanged(int value);
}

并使用作为

    int defaultVal = 10;
    mTextView.addTextChangedListener(new NumberChangedListener(mTextView, defaultVal) {
        @Override
        public void onNumberChanged(int value) {
            // use the parsed int
        }
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接