11

Consider:

TextView textView = new TextView(context);
    textView.addTextChangedListener(new TextWatcher() {

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

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

        @Override
        public void afterTextChanged(Editable s) {

            s.append("A");
        }
    });

If we add a TextWatcher to a TextView, and I want to append a letter to this TextView, every time the user writes a letter in it, but this keeps calling the TextWatcher Listener, so on to StackOverFlow error, so how can I append text without calling the TextWatcher Listener again?

4

5 回答 5

32

这很简单:

@Override
public void afterTextChanged(Editable s) {
    editText.removeTextChangedListener(this);
    //Any modifications at this point will not be detected by TextWatcher,
    //so no more StackOverflowError 
    s.append("A");
    editText.addTextChangedListener(this);
}
于 2013-06-08T23:59:30.637 回答
8

避免堆栈溢出的另一种方法:

TextView textView = new TextView(context);
    textView.addTextChangedListener(new TextWatcher() {

        boolean editing = false;

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

        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {
            if (!editing){
               editing = true;
               s.append("A");
               editing = false;
        }

    }
});
于 2015-03-04T21:38:45.253 回答
5

afterTextChanged 的​​文档说:

调用此方法是为了通知您,在 s 中的某处,文本已更改。从这个回调中对 s 进行进一步的更改是合法的,但请注意不要让自己陷入无限循环,因为您所做的任何更改都会导致再次递归调用此方法。(您不会被告知更改发生的位置,因为其他 afterTextChanged() 方法可能已经进行了其他更改并使偏移量无效。但是如果您需要在这里知道,您可以使用setSpan(Object, int, int, int)inonTextChanged(CharSequence, int, int, int)标记您的位置,然后从这里查找跨度结束了。

所以,与每一个s.append("A")call afterTextChanged()再等等。

于 2011-06-15T09:27:44.980 回答
0

一些伪代码,所以你可以这样做:

换个重点吧...

所以像这样:

tv.isFocusable = false

tv.setText("my new text")

tv.isFocusable = true // Maybe post this to the message queue, so other jobs finish fist.


// Later on in your listener:

if(tv.isFocusable && tv.hasFocus())
    // Do something
else ignore
于 2021-06-08T08:58:32.300 回答
-2

Kotlin 版本

editText.addTextChangedListener(object: TextWatcher {
    override fun afterTextChanged(s: Editable?) {
        if (s.toString().isNotBlank()) {

            val formattedValue: String = // Do some formatting

            editText.removeTextChangedListener(this)
            editText.setText(formattedValue)
            editText.setSelection(editText.text.toString().length)
            editText.addTextChangedListener(this)
        }
    }

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

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

    }

})
于 2017-11-01T07:39:28.333 回答