Skip to content

[Exposed Dropdown Menu] Filtering incorrectly applied after rotation #1464

Description

@mzgreen

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

Activity

  1. consp1racy commented on Jul 5, 2020

    @consp1racy
    Contributor

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

  2. mzgreen commented on Jul 5, 2020

    @mzgreen
    Author

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

  3. philips77 commented on Jul 31, 2020

    @philips77

    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.

  4. philips77 commented on Jul 31, 2020

    @philips77

    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;
    	}
    }
  5. wbervoets commented on Aug 27, 2020

    @wbervoets

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

  6. audiserg commented on Oct 2, 2020

    @audiserg

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

  7. arvind-codes commented on Oct 5, 2020

    @arvind-codes

    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];
                }
            };
    
        }
    
    }
  8. a2ke5e1 commented on Oct 15, 2020

    @a2ke5e1

    Thanks , It helps me a lot.

  9. YarikSOffice commented on Oct 21, 2020

    @YarikSOffice

    @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) 
    
  10. justdeko commented on Dec 26, 2020

    @justdeko

    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.

  11. Spikeysanju commented on Jan 27, 2021

    @Spikeysanju

    Is there any update on this issue?

  12. osquitoOfTheNorth commented on Feb 9, 2021

    @osquitoOfTheNorth

    Is there any update on this issue ?

  13. hanafey commented on Feb 14, 2021

    @hanafey

    For a simple pick list the following seems to work -- define a new ArrayAdapter.

    In Korlin it is used as follows:

            val arrayAdapterFilterControl = ArrayAdapterFilterControl(
                requireContext(), R.layout.spinner_list_item, fvm.mimeTypeList
            )
            arrayAdapterFilterControl.setNeverFilter(true)
    

    It also allows you to skip the false parameter setting in ```setText("Choice") and not truncate your selection list:

            ui.mimeTypeMenu.setText(fvm.mimeType.value)
    

    The never filter adapter is a trivial extension to ArrayAdapter

    package com.hanafey.android.weedkiller;
    
    import android.content.Context;
    import android.widget.ArrayAdapter;
    import android.widget.Filter;
    
    import androidx.annotation.NonNull;
    
    import java.util.List;
    
    public class ArrayAdapterFilterControl<T> extends ArrayAdapter<T> {
       // ...
        public ArrayAdapterFilterControl(@NonNull Context context, int resource, @NonNull T[] objects) {
            super(context, resource, objects);
        }
       // ...
        private Boolean neverFilter = false;
    
        public void setNeverFilter(Boolean state) {
            neverFilter = state;
        }
    
        @NonNull
        @Override
        public Filter getFilter() {
            if (!neverFilter) {
                return super.getFilter();
            } else {
                return new NeverFilter();
            }
        }
    
        private class NeverFilter extends Filter {
            protected FilterResults performFiltering(CharSequence prefix) {
                final FilterResults results = new FilterResults();
                return results;
            }
    
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (ArrayAdapterFilterControl.this.getCount() > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        }
    }
    
  14. 20 remaining items

  15. manabu-nakamura commented on Oct 22, 2024

    @manabu-nakamura
    Contributor
    import android.content.Context
    import android.os.Parcelable
    import android.util.AttributeSet
    import com.google.android.material.textfield.MaterialAutoCompleteTextView
    
    class MaterialAutoCompleteTextViewPatch @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = com.google.android.material.R.attr.autoCompleteTextViewStyle
    ) : MaterialAutoCompleteTextView(context, attrs, defStyleAttr) {
    
        override fun onRestoreInstanceState(state: Parcelable) {
            val threshold = getThreshold()
            // Make filter invalid temporarily
            setThreshold(Integer.MAX_VALUE)
            super.onRestoreInstanceState(state)
            setThreshold(threshold)
        }
    
    }

    can be simplified:

    import android.content.Context
    import android.os.Parcelable
    import android.util.AttributeSet
    import com.google.android.material.textfield.MaterialAutoCompleteTextView
    
    class MaterialAutoCompleteTextViewPatch @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = androidx.appcompat.R.attr.autoCompleteTextViewStyle
    ) : MaterialAutoCompleteTextView(context, attrs, defStyleAttr) {
        override fun onRestoreInstanceState(state: Parcelable) {
            val tmp = threshold
            // Make filter invalid temporarily
            threshold = Integer.MAX_VALUE
            super.onRestoreInstanceState(state)
            threshold = tmp
        }
    }
  16. added a commit that references this issue on Dec 25, 2024
  17. manabu-nakamura commented on Feb 1, 2025

    @manabu-nakamura
    Contributor
  18. qwertyfinger commented on Aug 15, 2025

    @qwertyfinger

    76dce73

    Why was this fix reverted in 1.13.0-alpha11? This issue still persists and 1.13.0-alpha10 is the only version that works properly.

  19. manabu-nakamura commented on Aug 15, 2025

    @manabu-nakamura
    Contributor

    76dce73

    Why was this fix reverted in 1.13.0-alpha11? This issue still persists and 1.13.0-alpha10 is the only version that works properly.

    I don't know.
    @drchen, do you know?

  20. drchen commented on Aug 15, 2025

    @drchen
    Contributor

    The fix broke some apps who are implementing their own saved state logic. We need to figure out a better solution unfortunately.

  21. reopened this on Aug 15, 2025
  22. removed their assignment
    on Aug 18, 2025
  23. manabu-nakamura commented on Aug 25, 2025

    @manabu-nakamura
    Contributor

    I also reported this to the Issue Tracker: https://issuetracker.google.com/issues/322066510

    Status:​ Assigned -> Won't Fix (Obsolete)

  24. manabu-nakamura commented on Jan 25, 2026

    @manabu-nakamura
    Contributor

    The fix broke some apps who are implementing their own saved state logic. We need to figure out a better solution unfortunately.

    Can you provide "a minimal sample app that reproduces the issue"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions