Material-components-android: [TextInputLayout] [Exposed Dropdown Menu] Set a default selection

Created on 11 Feb 2020  路  13Comments  路  Source: material-components/material-components-android

Description: I am going to select default selection programmatically but its not working.

but none of them working.

Source code:
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="hint_text">

    <AutoCompleteTextView
        android:id="@+id/filled_exposed_dropdown"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</com.google.android.material.textfield.TextInputLayout>

     var eqList = ArrayList<String>()
      eqList.add(getString(R.string.linear_equation))
     eqList.add(getString(R.string.quad_equation))
      eqList.add(getString(R.string.cubic_equation))
      val eqAdapter = ArrayAdapter<String>(this,
            R.layout.row_spinner_item, eqList)
     eqAdapter.setDropDownViewResource(R.layout.row_spinner_dropdown_item)
     filled_exposed_dropdown.setAdapter(eqAdapter)
    filled_exposed_dropdown.listSelection = 0    // Not working
    filled_exposed_dropdown.setSelection(0)     // Not working

Material Library version: 1.2.0-alpha04

Device: All

bug

Most helpful comment

Hi, since the menu uses an AutoCompleteTextView, the way to set a default selection is by calling setText(CharSequence text, boolean filter), with the filter=false to have the filtering off. Will update the documentation with this info.

So you'd do something like:
filled_exposed_dropdown.setText(eqAdapter.getItem(0).toString(), false);

note that this won't survive configuration changes. after a configuration change the item is selected again, but with filtering. items not matching the filter aren't visible anymore.

All 13 comments

Hi, since the menu uses an AutoCompleteTextView, the way to set a default selection is by calling setText(CharSequence text, boolean filter), with the filter=false to have the filtering off. Will update the documentation with this info.

So you'd do something like:
filled_exposed_dropdown.setText(eqAdapter.getItem(0).toString(), false);

Hi, since the menu uses an AutoCompleteTextView, the way to set a default selection is by calling setText(CharSequence text, boolean filter), with the filter=false to have the filtering off. Will update the documentation with this info.

So you'd do something like:
filled_exposed_dropdown.setText(eqAdapter.getItem(0).toString(), false);

note that this won't survive configuration changes. after a configuration change the item is selected again, but with filtering. items not matching the filter aren't visible anymore.

@wondering639 Anyway to the make filter visible on configuration change ? I am facing similar issue when I go back to the fragments with navigation components, the filter options are not visible anymore.

@blacpythoz I solved (workaround) it by creating a non filtering adapter as described in this article: https://medium.com/@rmirabelle/there-is-no-material-design-spinner-for-android-3261b7c77da8

@wondering639 is right. setting filtering to false doesn't survive configuration change. I doubt that this is intended behavior.

Ref: #1464

@qrezet @wondering639

filled_exposed_dropdown.setText(eqAdapter.getItem(0).toString(), false);

note that this won't survive configuration changes. after a configuration change the item is selected again, but with filtering. items not matching the filter aren't visible anymore.

You can use

filled_exposed_dropdown.setFreezesText(false);

The EditText sets the freezesText=true. Due to this value after the rotation the TextView#onRestoreInstanceState(Parcelable) calls autoCompleteTextView.setText(value,true) which applies a filter to the adapter values.

@gabrielemariotti Thank you, but - without testing it - shouldn't it be autoCompleteTextView.setText(value,false) instead of autoCompleteTextView.setText(value,true)? Because we want _no_ filtering.

@wondering639 I try to explain better.

To select a default value you have to use:
autoCompleteTextView.setText(value, false);

After a rotation or a configuration change the value is still visible but with filtering. Items not matching the filter aren't visible anymore. It happens because the TextView#onRestoreInstanceState(Parcelable) calls autoCompleteTextView.setText(value,true) and you can't change it. You can only prevent this call using:

autoCompleteTextView.setFreezesText(false);

In this way the TextView#onRestoreInstanceState(Parcelable) doesn't call autoCompleteTextView.setText(value,true).

@wondering639 I try to explain better.

To select a default value you have to use:
autoCompleteTextView.setText(value, false);

After a rotation or a configuration change the value is still visible but with filtering. Items not matching the filter aren't visible anymore. It happens because the TextView#onRestoreInstanceState(Parcelable) calls autoCompleteTextView.setText(value,true) and you can't change it. You can only prevent this call using:

autoCompleteTextView.setFreezesText(false);

In this way the TextView#onRestoreInstanceState(Parcelable) doesn't call autoCompleteTextView.setText(value,true).

got it, thanks 馃憤

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

    }

}

@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)聽
Was this page helpful?
0 / 5 - 0 ratings