Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OnTextChanged is triggered on orientationChange even if TextWatcher is set after onCreate method

Tags:

android

I've been trying to get specific behaviour with EditText. This is my simple activity with rotation enabled. When I enter some text, onTextChanged method is triggered.

When I rotate the phone, this method should not be triggered, bacause the text, which was saved in onInstanceState is already set into EditText in onCreate method.

However, when I rotate the phone back to its original orientation, method triggers again! See logcat at the end of this post.

This is a copy and paste code from a newly created Android Studio project.

public class MainActivity extends AppCompatActivity {

    EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = (EditText) findViewById(R.id.search_query);
    }

    @Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                Log.d("MainActivity", "charSequence:" + charSequence);
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }
}

UPD:

Android retains text in all editText fields (with unique ID) on each orientation change by default. That is why onTextChanged is triggered when I rotate my phone. To avoid this I placed onTextChanged listener after onCreate, so it will listen events after text is set to EditText. But it does NOT WORK as expected(logcat). Check the last link for more info

logcat:

 D/MainActivity: onCreate
 D/MainActivity: charSequence:a //entered manually
 D/MainActivity: charSequence:a // triggered on orientation change
 D/MainActivity: onDestroy
 D/MainActivity: onCreate
 D/MainActivity: onDestroy
 D/MainActivity: onCreate
 D/MainActivity: onDestroy
 D/MainActivity: onCreate
 D/MainActivity: onDestroy // no callback so far
 D/MainActivity: onCreate
 D/MainActivity: charSequence:ba // entered manyally
 D/MainActivity: onDestroy
 D/MainActivity: onCreate
 D/MainActivity: charSequence:ba // when came back to original "ba" orientation
 D/MainActivity: onDestroy
 D/MainActivity: onCreate

Relevant: TextWatcher called even if text is set before adding the watcher

Android retain callback state after configuration change

like image 601
nutella_eater Avatar asked Jul 11 '17 13:07

nutella_eater


1 Answers

Take a look at this acticle, especially at:

You can notice that the text in the first EditText (with ID) will keep no change after orientation changed, and onTextChanged() method of the TextChangedListener will be called also, to update the TextView.

On the other hand, the second EditText (without ID assigned) will clear to empty when orientation changed.

Anyway, You can suppress onTextChanged() like in this answer of athor:

...you can get around it by either:

  • Removing the TextWatcher before you set the text, and adding it back after.
  • Or set a boolean flag before you set the text, which tells the TextWatcher to ignore it.

E.g.

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

And in your 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) {

     } });
like image 51
Andrii Omelchenko Avatar answered Oct 13 '22 21:10

Andrii Omelchenko