Differences between TextWatcher 's onTextChanged, beforeTextChanged and afterTextChanged
Asked Answered
S

5

60

In my Android project, I have had to add a TextChangedListener (TextWatcher) to an edit text view. And there are three parts to it:

  • onTextChanged()
  • beforeTextChanged()
  • afterTextChanged()

What are the differences of these three? I have had to implement a search of a table on the key listener and for my case all these three looked the same. Also they functioned the same. When I input a part of a product name, the table redraws with only those products that contain entered text in it. But I used the afterTextChanged() part. My code is:

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

So can someone give me an explanation on these three?

Saldivar answered 29/11, 2013 at 4:28 Comment(1)
You might find this thread helpful #477348Confounded
D
34

onTextChanged runs during the text changing.

afterTextChanged runs immediately after the text is changed.

beforeTextChanged runs the instant before the text is changed.

Depending on when you want to assign variables or do things, you may want to run the code the instant before the change, or the instant after.

Here is an example of this:

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

In this case, let's say you changed the text from "h" to "hi", the output would be:

before: "h"
on: "hi"
after: "hi"

Decreasing answered 29/11, 2013 at 5:4 Comment(1)
So, What's different between onTextChanged and afterTextChanged ?Trow
S
99

The parameters for beforeTextChanged and onTextChanged are a little hard to understand at first. It may be helpful to see them being used in an example. Watch the following demonstration a few times. Pay attention to the counts.

  • The red highlight is the old text that is about to be replaced by the green text.
  • The green highlight is the new text that just replaced the red text.

enter image description here

beforeTextChanged

  • start is the start index of the red highlighted text (that is about to be deleted)
  • count is the length of the red highlighted text (that is about to be deleted)
  • after is the length of the green highlighted text (that is about to be added)

onTextChanged

  • start is the start index of the green highlighted text (that just got added).
    This is the same as the start of beforeTextChanged.
  • before is the length of the red highlighted text (that just got deleted).
    This is the same as the count of beforeTextChanged.
  • count is the length of the green highlighted text (that just got added).
    This is the same as the after of beforeTextChanged.

afterTextChanged

  • editable is the editable text from the EditText. You are allowed to change it here. Doing so will trigger all the TextWatcher events again.
  • You are not given any information about what was changed. If you want to know, you can set a span in onTextChanged and then look up the span here.

When to use which?

If you want to observe the changes being made, use beforeTextChanged() or onTextChanged(). You are not allowed to change the CharSequence text in either of these methods, though.

If you want to further modify the text after it was changed, do it in afterTextChanged().

Code

Here is the code if you want to play around with it yourself.

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>
Subeditor answered 13/11, 2017 at 11:15 Comment(0)
D
34

onTextChanged runs during the text changing.

afterTextChanged runs immediately after the text is changed.

beforeTextChanged runs the instant before the text is changed.

Depending on when you want to assign variables or do things, you may want to run the code the instant before the change, or the instant after.

Here is an example of this:

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

In this case, let's say you changed the text from "h" to "hi", the output would be:

before: "h"
on: "hi"
after: "hi"

Decreasing answered 29/11, 2013 at 5:4 Comment(1)
So, What's different between onTextChanged and afterTextChanged ?Trow
M
26

Android TextChangedListener is one kind of trigger which is called on text change of an input field.

TextChangedListener has three events.

1.beforeTextChanged : This means that the characters are about to be replaced with some new text. The text is uneditable. This event is used when you need to take a look at the old text which is about to change.

2.onTextChanged: Changes have been made, some characters have just been replaced. The text is uneditable. This event is used when you need to see which characters in the text are new.

3.afterTextChanged : The same as above, except now the text is editable. This event is used when you need to see and possibly edit new text.

Moonlit answered 29/11, 2013 at 4:49 Comment(4)
what if I need to concern on changing of the text, I mean after the change. I used the same code snippet I mentioned up in afterTextChanged on each of others. It gave me the same output.Saldivar
I didnt got what you are trying to say! ontextchanged and aftertextchange will give same outputMoonlit
When you say the text is editable/uneditable, what does "text" mean?Vaporous
@Jonas, it means the parameter i.e.(s) on afterTextChanged can be edited or changed to something else; while it cannot be edited or changed on the other two events(onTextChanged and beforeTextChanged)....rather, on the other two, it just informs you that something withing that "s" has changed. It also shows how much changed, when change started and ended.Coitus
A
1
  • abstract void afterTextChanged(Editable s)

This method is called to notify you that, somewhere within s, the text has been changed.

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

This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after.

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

This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before.

You can more learn here.

Aerosphere answered 29/11, 2013 at 4:47 Comment(0)
Z
0
  1. afterTextChanged (Editable s) - This method is called when the text has been changed. Because any changes you make will cause this method to be called again recursively, you have to be watchful about performing operations here, otherwise it might lead to infinite loop.

  2. beforeTextChanged (CharSequence s, int start, int count, int after) - This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback.

  3. onTextChanged (CharSequence s, int start, int before, int count) - This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.

Zashin answered 16/11, 2015 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.