Material-components-android: [Exposed Dropdown Menu] Filtering incorrectly applied after rotation

Created on 5 Jul 2020  路  11Comments  路  Source: material-components/material-components-android

Description: It seems that in some cases filtering is incorrectly applied to AutocompleteTextView after rotating the device which causes that all options except for the selected one disappear from Dropdown Menu.

Steps to reproduce:

  1. Open Material Catalog app
  2. Go to TextField -> Exposed Dropdown Menu Demo
  3. Tap on 4th TextField from the top and select any value from the dropdown menu.
  4. Rotate the device to landscape and back to portrait
  5. Try to select a value from any of the 4 TextFields

The result is that those Dropdowns are now showing only 1 value instead of all of them.

Expected behavior: All TextField Dropdown Menus should show all values after device rotations

Android API version: Tested on Android 10 and Android 11 Beta

Material Library version: Checked on 1.3.0-alpha01 and 1.2.0-beta01

Device: Google Pixel 3 and Emulator

bug

Most helpful comment

FIX: All the values will be visible after the device rotation and also the selected value will be displayed.

public class TextInputDropDownMenu extends AppCompatAutoCompleteTextView {

    public TextInputDropDownMenu(@NonNull Context context) {
        super(context);
    }

    public TextInputDropDownMenu(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public TextInputDropDownMenu(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    {
        setInputType(InputType.TYPE_NULL);
    }

    @Override
    public boolean getFreezesText() {
        return false;
    }

    @Override
    public Parcelable onSaveInstanceState() {
        Parcelable parcelable = super.onSaveInstanceState();
        if (TextUtils.isEmpty(getText())) {
            return parcelable;
        }

        CustomSavedState customSavedState = new CustomSavedState(parcelable);
        customSavedState.text = getText().toString();
        return customSavedState;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof CustomSavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }

        CustomSavedState customSavedState = (CustomSavedState) state;
        setText(customSavedState.text, false);
        super.onRestoreInstanceState(customSavedState.getSuperState());
    }

    private static final class CustomSavedState extends BaseSavedState {

        private String text;

        public CustomSavedState(Parcelable superState) {
            super(superState);
        }

        public CustomSavedState(Parcel source) {
            super(source);
            text = source.readString();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeString(text);
        }

        private static final Creator<CustomSavedState> CREATOR = new Creator<CustomSavedState>() {
            @Override
            public CustomSavedState createFromParcel(Parcel source) {
                return new CustomSavedState(source);
            }

            @Override
            public CustomSavedState[] newArray(int size) {
                return new CustomSavedState[size];
            }
        };

    }

}

All 11 comments

Hi, you'll want to include a small project that reproduces the issue.

@consp1racy it's reproducible using Material Catalog sample app.

This is because getFreezesText() returns always true for EditText. After rotation setText(CharSequence) is called in TextView#onRestoreInstanceState(Parcelable), which by default does the filtering.

I workaround it by overriding getFreezesText() and returning false, but then I have to set the value manually.

public class ExposedDropdownMenu extends MaterialAutoCompleteTextView {

    public ExposedDropDown(@NonNull final Context context, @Nullable final AttributeSet attributeSet) {
        super(context, attributeSet);
    }

    @Override
    public boolean getFreezesText() {
        return false;
    }
}

I have the same issue :( I tried calling setFreezesText(false); but that doesn't help, the suggested by @philips77 method works fine, but can we have an official solution?

same problem here, hoping for a fix in the next version 馃憤

I have a same bug when i back via navigation component on my fragment where i allready select some item in dropdown
autoCompleteTextView.setFreezesText(false) - This not help me
i am avoid bug by next trick:
override fun onPause() {
super.onPause()
etSelectDropdown.setText("",false)
}

FIX: All the values will be visible after the device rotation and also the selected value will be displayed.

public class TextInputDropDownMenu extends AppCompatAutoCompleteTextView {

    public TextInputDropDownMenu(@NonNull Context context) {
        super(context);
    }

    public TextInputDropDownMenu(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public TextInputDropDownMenu(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    {
        setInputType(InputType.TYPE_NULL);
    }

    @Override
    public boolean getFreezesText() {
        return false;
    }

    @Override
    public Parcelable onSaveInstanceState() {
        Parcelable parcelable = super.onSaveInstanceState();
        if (TextUtils.isEmpty(getText())) {
            return parcelable;
        }

        CustomSavedState customSavedState = new CustomSavedState(parcelable);
        customSavedState.text = getText().toString();
        return customSavedState;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof CustomSavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }

        CustomSavedState customSavedState = (CustomSavedState) state;
        setText(customSavedState.text, false);
        super.onRestoreInstanceState(customSavedState.getSuperState());
    }

    private static final class CustomSavedState extends BaseSavedState {

        private String text;

        public CustomSavedState(Parcelable superState) {
            super(superState);
        }

        public CustomSavedState(Parcel source) {
            super(source);
            text = source.readString();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeString(text);
        }

        private static final Creator<CustomSavedState> CREATOR = new Creator<CustomSavedState>() {
            @Override
            public CustomSavedState createFromParcel(Parcel source) {
                return new CustomSavedState(source);
            }

            @Override
            public CustomSavedState[] newArray(int size) {
                return new CustomSavedState[size];
            }
        };

    }

}

Thanks , It helps me a lot.

@ar-arvind
Your solution produces a crash while testing it agains the process death scenario (Terminate Application button in android studio, for example):

2020-10-21 11:32:30.553 14482-14482/com.example.sample E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.sample, PID: 14482
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sample.MainActivity}: java.lang.RuntimeException: Parcel android.os.Parcel@aae25dd: Unmarshalling unknown type code 7209033 at offset 2716
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@aae25dd: Unmarshalling unknown type code 7209033 at offset 2716
        at android.os.Parcel.readValue(Parcel.java:2444)
        at android.os.Parcel.readSparseArrayInternal(Parcel.java:2813)
        at android.os.Parcel.readSparseArray(Parcel.java:2068)
        at android.os.Parcel.readValue(Parcel.java:2422)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:2732)
        at android.os.BaseBundle.unparcel(BaseBundle.java:269)
        at android.os.Bundle.getSparseParcelableArray(Bundle.java:934)
        at androidx.fragment.app.FragmentStateManager.restoreState(FragmentStateManager.java:236)
        at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2473)
        at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:196)
        at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:287)
        at androidx.appcompat.app.AppCompatActivity.onCreate(AppCompatActivity.java:115)
        at com.example.sample.MainActivity.onCreate(MainActivity.kt:12)
        at android.app.Activity.performCreate(Activity.java:6679)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)聽
        at android.app.ActivityThread.-wrap12(ActivityThread.java)聽
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)聽
        at android.os.Handler.dispatchMessage(Handler.java:102)聽
        at android.os.Looper.loop(Looper.java:154)聽
        at android.app.ActivityThread.main(ActivityThread.java:6119)聽
        at java.lang.reflect.Method.invoke(Native Method)聽
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)聽
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)聽

are there any updates on this issue?
additionally, i get a "mini-bug" (not sure if this is expected behavior) that the autocomplete menu pops up when i change the configuration and the autocomplete textview is selected.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ahmaducg picture ahmaducg  路  3Comments

magnusfernandes picture magnusfernandes  路  3Comments

TdevM picture TdevM  路  3Comments

sepehr-alipour picture sepehr-alipour  路  3Comments

mnayef95 picture mnayef95  路  3Comments