TextWatcher的onTextChanged、beforeTextChanged和afterTextChanged之间的区别

59
在我的Android项目中,我不得不向编辑文本视图添加一个TextChangedListener(TextWatcher),它分为三个部分:
  • onTextChanged()
  • beforeTextChanged()
  • afterTextChanged()
这三个有什么区别?我需要在按键监听器中实现表格搜索,在我的情况下,这三个看起来都一样。它们也起到了相同的作用。当我输入产品名称的一部分时,表格会重新绘制,只显示包含输入文本的产品。但是我使用了afterTextChanged()部分。我的代码如下:
EditProduct.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            // TODO Auto-generated method stub

            // System.out.println("onTextChanged"+s);
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // TODO Auto-generated method stub
            // System.out.println("beforeTextChanged"+s);
        }

        @Override
        public void afterTextChanged(Editable s) {
            // TODO Auto-generated method stub
            // System.out.println("afterTextChanged"+s);

            String new_prx = s.toString();

            System.out.println(s);
            mini_productList = new ArrayList<Product>();

            // mini_productList
            int count = 0;
            if (new_prx.equals("")) {

                loadtableProducts(productList);

            } else {

                for (int i = 0; i < productList.size(); i++) {

                    if (productList.get(i).getDescription().toString()
                            .substring(0, (new_prx.length()))
                            .equalsIgnoreCase(new_prx)) {
                        mini_productList.add(productList.get(i));
                        count++;

                    }
                }

                loadtableProducts(mini_productList);
            }
        }
    });

那么,有人能给我解释一下这三个是什么吗?


1
你可能会发现这个线程有帮助:https://dev59.com/-HRB5IYBdhLWcg3w4bKv - Abhishek V
5个回答

98

beforeTextChangedonTextChanged的参数起初有点难理解。观看以下示例演示几次可能会有帮助。请注意计数。

  • 红色高亮显示的是即将被绿色文本替换的旧文本。
  • 绿色高亮显示的是刚刚替换红色文本的新文本。

enter image description here

beforeTextChanged

  • start 是即将被删除的红色高亮文本的起始索引。
  • count 是即将被删除的红色高亮文本的长度。
  • after 是即将添加的绿色高亮文本的长度。

onTextChanged

  • start 是刚刚添加的绿色高亮文本的起始索引。这与beforeTextChanged中的start相同。
  • before 是刚刚删除的红色高亮文本的长度。这与beforeTextChanged中的count相同。
  • count 是刚刚添加的绿色高亮文本的长度。这与beforeTextChanged中的after相同。

afterTextChanged

  • editable 是来自EditText的可编辑文本。您可以在此更改它。这样做会再次触发所有TextWatcher事件。
  • 您没有任何关于更改内容的信息。如果您想知道,可以在onTextChanged中设置一个span,然后在此处查找该span。

何时使用哪个?

如果您想观察到正在进行的更改,请使用beforeTextChanged()onTextChanged()。但是,在这些方法中,您不允许更改CharSequence文本。
如果您想在更改后进一步修改文本,请在afterTextChanged()中进行。

代码

以下是代码,如果您想自己尝试玩耍。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    final static int RED_COLOR = Color.parseColor("#fb7373");
    final static int GREEN_COLOR = Color.parseColor("#40de83");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText editText = findViewById(R.id.editText);
        final TextView tvBeforeText = findViewById(R.id.tvBeforeText);
        final TextView tvBeforeNumbers = findViewById(R.id.tvBeforeNumbers);
        final TextView tvAfterText = findViewById(R.id.tvAfterText);
        final TextView tvAfterNumbers = findViewById(R.id.tvAfterNumbers);

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                SpannableString spannableString = new SpannableString(s);
                BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(RED_COLOR);
                spannableString.setSpan(backgroundSpan, start, start + count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                tvBeforeText.setText(spannableString);
                tvBeforeNumbers.setText("start=" + start + "  count=" + count + " after=" + after);
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                SpannableString spannableString = new SpannableString(s);
                BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(GREEN_COLOR);
                spannableString.setSpan(backgroundSpan, start, start + count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                tvAfterText.setText(spannableString);
                tvAfterNumbers.setText("start=" + start + " before=" + before + " count=" + count);
            }

            @Override
            public void afterTextChanged(Editable s) {
                Log.i("TAG", "afterTextChanged: " + s);
            }
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="beforeTextChanged" />

    <TextView
        android:id="@+id/tvBeforeText"
        android:textSize="17sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvBeforeNumbers"
        android:textSize="17sp"
        android:text="start=0 count=0 after=0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_marginTop="20dp"
        android:text="onTextChanged" />

    <TextView
        android:id="@+id/tvAfterText"
        android:textSize="17sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvAfterNumbers"
        android:textSize="17sp"
        android:text="start=0 count=0 after=0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

34

onTextChanged 在文本变化期间运行。

afterTextChanged 在文本被更改后立即运行。

beforeTextChanged 在文本更改之前立即运行。

根据您想要何时分配变量或执行操作,您可能希望在更改之前立即运行代码,或在更改之后立即运行代码。

这里是一个示例:

String afterTextChanged = "";
String beforeTextChanged = "";
String onTextChanged = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et = (EditText)findViewById(R.id.editText);

    et.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int st, int b, int c) 
        {
            onTextChanged = et.getText().toString();
        }

        @Override
        public void beforeTextChanged(CharSequence s, int st, int c, int a) 
        {
            beforeTextChanged = et.getText().toString();
        }

        @Override
        public void afterTextChanged(Editable s) 
        {
            afterTextChanged = et.getText().toString();
            Toast.makeText(Activity.this, "before: " + beforeTextChanged
                                           + '\n' + "on: " + onTextChanged 
                                           + '\n' + "after: " + afterTextChanged
                           ,Toast.LENGTH_SHORT).show();
        }
    });
}

假设你将文本从 "h" 改为 "hi",输出如下:

之前:"h"
改为:"hi"
之后:"hi"


11
onTextChanged和afterTextChanged有什么不同? - krosshj

26

TextChangedListener 是一种在输入字段文本更改时被调用的触发器。

TextChangedListener 有三个事件:

1.beforeTextChanged:这表示字符将被新文本替换。文本不可编辑。当需要查看即将更改的旧文本时使用此事件。

2.onTextChanged:已进行更改,某些字符刚被替换。文本不可编辑。当需要查看文本中哪些字符是新的时使用此事件。

3.afterTextChanged:与上述相同,但现在文本可以编辑。当你需要查看并可能编辑新文本时,请使用此事件。


如果我需要关注文本的更改,也就是在更改后。我在每个其他地方都使用了我之前提到的相同的代码片段,在afterTextChanged中。它给了我相同的输出。 - Samantha Withanage
我不明白你想说什么!ontextchanged和aftertextchange将会给出相同的输出。 - Jigar Pandya
2
当你说文本是可编辑/不可编辑时,“文本”是指什么? - Jonas
@Jonas,这意味着afterTextChanged中的参数i.e.(s)可以被编辑或更改为其他内容;而在另外两个事件(onTextChanged和beforeTextChanged)中无法进行编辑或更改...相反,在另外两个事件中,它只是通知您“s”中的某些内容已更改。它还显示了有多少内容发生了变化,变化何时开始和结束。 - pasignature

1
  • abstract void afterTextChanged(Editable s)

此方法用于通知您,s 中的某个位置已更改文本。

  • abstract void beforeTextChanged(CharSequence s, int start, int count, int after)

此方法用于通知您,在 s 中,从 start 开始计数个字符将被新文本替换,新文本长度为 after。

  • abstract void onTextChanged(CharSequence s, int start, int before, int count)

此方法用于通知您,在 s 中,从 start 开始计数个字符刚刚替换了具有长度 before 的旧文本。

您可以在 这里 更多了解。


0
  1. afterTextChanged (Editable s) - 当文本被更改时,将调用此方法。由于您所做的任何更改都会导致递归地再次调用此方法,因此您必须注意在此处执行操作,否则可能会导致无限循环。

  2. beforeTextChanged (CharSequence s, int start, int count, int after) - 此方法被调用以通知您,在s中,从start开始的count个字符即将被长度为after的新文本替换。尝试从此回调中对s进行更改是错误的。

  3. onTextChanged (CharSequence s, int start, int before, int count) - 此方法被调用以通知您,在s中,从start开始的count个字符刚刚替换了具有长度before的旧文本。尝试从此回调中对s进行更改是错误的。


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