Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TextInputLayout] [Exposed Dropdown Menu] Set a default selection #1007

Closed
Slake07 opened this issue Feb 11, 2020 · 24 comments
Closed

[TextInputLayout] [Exposed Dropdown Menu] Set a default selection #1007

Slake07 opened this issue Feb 11, 2020 · 24 comments

Comments

@Slake07
Copy link

Slake07 commented Feb 11, 2020

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

but none of them working.

Source code:

<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

@Slake07 Slake07 added the bug label Feb 11, 2020
@leticiarossi leticiarossi self-assigned this Mar 9, 2020
@leticiarossi
Copy link
Contributor

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

@leticiarossi leticiarossi changed the title [TextInputLayout] [Exposed Dropdown Menu][Component name] Short description of issue [TextInputLayout] [Exposed Dropdown Menu] Set a default selection Mar 9, 2020
@wondering639
Copy link

wondering639 commented Mar 9, 2020

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.

@subashz
Copy link

subashz commented May 11, 2020

@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.

@wondering639
Copy link

@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

@qrezet
Copy link

qrezet commented Jun 20, 2020

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

@philips77
Copy link

Ref: #1464

@gabrielemariotti
Copy link
Contributor

gabrielemariotti commented Aug 15, 2020

@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.

@wondering639
Copy link

@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.

@gabrielemariotti
Copy link
Contributor

@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
Copy link

@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 👍

@audiserg
Copy link

audiserg commented Oct 2, 2020

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

@arvind-codes
Copy link

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

    }

}

@YarikSOffice
Copy link

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

@Imadlekal
Copy link

Did anyone manage to get a fix for this?

@drchen
Copy link
Contributor

drchen commented Jun 9, 2022

We are working with the Framework and Androidx team to figure out a good solution of this. (List gets filtered after configuration change.)

The tracking issue is here: #1464

@Imadlekal
Copy link

Has there been a fix for this?

We are working with the Framework and Androidx team to figure out a good solution of this. (List gets filtered after configuration change.)

The tracking issue is here: #1464

I appreciate the fast response. My problem was that the filtering got triggered even if I set it to false. In other words, the text was there on application startup, but there was no way to change it again (I didn't have similar values).

Using setText with PostDelayed did the trick for me.

@drchen
Copy link
Contributor

drchen commented Jun 9, 2022

Can you provide more details? Is your issue different from the one after configuration change?

@Imadlekal
Copy link

I'm not sure what you mean by "configuration change" but I was trying to set a default value for my AutoCompleteTextView. The following was not working:

autoCompleteTextView.setText( arrayAdapter.getItem(1)?.paymentMethodName, false

The behavior I got:

The text is set properly, but if I click again on the DropDownMenu, it doesn't open. I'm guessing because the filter was ON although I'm explicitly setting it to false as you can see.

Doing this:

   exchangeBinding.autoCompleteTextView.postDelayed(Runnable {
            exchangeBinding.autoCompleteTextView.setText(
                arrayAdapter.getItem(1)?.paymentMethodName,
                false
            )

    
        }, 10)

Fixed the problem.

@drchen
Copy link
Contributor

drchen commented Jun 9, 2022

I meant after the view is recreated by the framework.

Are you setting a default value right after the view is created/inflated?

@Imadlekal
Copy link

I haven't tried that actually.

And to answer your question, yes, that's what I'm doing. Is that the wrong way to go by it?

@drchen
Copy link
Contributor

drchen commented Jun 9, 2022

I think that might be a bug on our end. I need to check. : )

@drchen drchen reopened this Jun 9, 2022
@drchen drchen assigned drchen and leticiarossi and unassigned leticiarossi Jun 9, 2022
@drchen
Copy link
Contributor

drchen commented Jun 9, 2022

Hi @Imadlekal - I cannot reproduce what you said. Can you provide a minimal repro app so we can debug?

Or at least more detailed code snippet regarding how you inflate and set up your AutoCompleteTextView.

@drchen
Copy link
Contributor

drchen commented Jun 27, 2022

I'll close this issue for now due to no further info available. Please feel free to reopen it with a repro.

@drchen drchen closed this as completed Jun 27, 2022
@enricocid
Copy link

Record_2022-09-26-15-28-59.mp4

To solve the list filtering issue after a configuration change I set

isSaveEnabled = false

when instantiating the drop down menu

full code:

_eqFragmentBinding?.autoCompleteTextView?.run {
    setSimpleItems(mPresetsList.toTypedArray())
    isSaveEnabled = false
    setText(mPresetsList[mSelectedPreset], false)
    setOnItemClickListener { _, _, newPreset, _ ->
        // Respond to item chosen
        mSelectedPreset = newPreset
        mEqualizer?.first?.usePreset(mSelectedPreset.toShort())
        updateBandLevels(isPresetChanged = true)
    }
}

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

No branches or pull requests