Reputation: 1217
I have the following AutoCompleteTextView:
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/offering_type_dropdown_layout"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/date_card_spacing"
android:layout_marginStart="4dp"
app:layout_constraintStart_toEndOf="@+id/offering_details_header_image"
app:layout_constraintEnd_toStartOf="@+id/offering_details_date_layout"
app:layout_constraintTop_toTopOf="parent"
android:hint="@string/offering_type_hint">
<AutoCompleteTextView
android:id="@+id/offering_details_type_dropdown"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textNoSuggestions"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:cursorVisible="false"/>
</com.google.android.material.textfield.TextInputLayout>
In my Activity's onCreate
, I fill the AutoCompleteTextView like this:
String[] TYPES = new String[] {getString(R.string.burnt_offering), getString(R.string.meal_offering), getString(R.string.peace_offering), getString(R.string.sin_offering)};
ArrayAdapter<String> adapter = new ArrayAdapter<>(OfferingInputActivity.this, R.layout.offering_types_dropdown, TYPES);
mOfferingTypeCombo.setAdapter(adapter);
Then I populate the view using a Room database and preselect one of the values. In the Room callback, I do:
mOfferingTypeCombo.setText(getString(R.string.meal_offering)), false);
Everything works well on the initial run, and the dropdown is shown correctly:
Now I rotate the device to landscape. The very same code as above is executed but this time, the dropdown box only shows the current selection:
For some reason, all other entries in the adapter have disappeared. I have tried hacks such as setAdapter(null)
before I set the adapter, but no success. Can someone tell me why after rotation, the dropdown is missing entries even though the exact same code is executed?
Upvotes: 15
Views: 4281
Reputation: 87
This fix on the GitHub issue seems to work:
autoCompleteTextView.isSaveEnabled = false
Upvotes: 1
Reputation: 81
To solve this issue when orientation changes add this in XML
android:saveEnabled="false"
Upvotes: 2
Reputation: 63
The solution proposed by @Mohsents worked for me. This is the java version of his code that I used:
public class NoFilterArrayAdapter extends ArrayAdapter<Object> {
public NoFilterArrayAdapter(Context context, int resource) {
super(context, resource);
}
public NoFilterArrayAdapter(Context context, int resource, Object[] objects) {
super(context, resource, objects);
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
}
};
}
}
Upvotes: 1
Reputation: 1
Code:
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/inputAddress"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/Address">
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
/>
</com.google.android.material.textfield.TextInputLayout>
list_item.xml
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="?attr/textAppearanceSubtitle1"
/>
fragment.class
class CashierAddFragment : Fragment() {
var mBinding: FragmentCashierAddBinding? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = FragmentCashierAddBinding.inflate(inflater, container, false)
if(savedInstanceState == null) {
initAddressSpinner(binding, "")
} else {
initAddressSpinner(binding, savedInstanceState.getString(KEY_ADDRESS))
}
mBinding = binding
return binding.root
}
override fun onSaveInstanceState(outState: Bundle) {
val address = mBinding!!.inputAddress.getTrimText()
outState.putString(KEY_ADDRESS, address)
super.onSaveInstanceState(outState)
}
private fun initAddressSpinner(binding: FragmentCashierAddBinding, initValue: String?) {
val items = listOf("Option 1", "Option 2", "Option 3", "Option 4")
val adapter = ArrayAdapter(requireContext(), R.layout.list_item, items)
val autoTxtAddress = binding.inputAddress.editText as? AutoCompleteTextView
autoTxtAddress?.setText(initValue)
autoTxtAddress?.setAdapter(adapter)
}
}
Upvotes: 0
Reputation: 760
This custom MaterialAutoCompleteTextView
resolves all problems:
class ExposedDropdownMenu : MaterialAutoCompleteTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun getFreezesText(): Boolean {
return false
}
init {
inputType = InputType.TYPE_NULL
}
override fun onSaveInstanceState(): Parcelable? {
val parcelable = super.onSaveInstanceState()
if (TextUtils.isEmpty(text)) {
return parcelable
}
val customSavedState = CustomSavedState(parcelable)
customSavedState.text = text.toString()
return customSavedState
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state !is CustomSavedState) {
super.onRestoreInstanceState(state)
return
}
setText(state.text, false)
super.onRestoreInstanceState(state.superState)
}
private class CustomSavedState(superState: Parcelable?) : BaseSavedState(superState) {
var text: String? = null
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeString(text)
}
}
}
Note: It may not works correctly in older APIs like 23 or below.
one way is using a custom ArrayAdapter
that prevents to Filter texts.
class NoFilterArrayAdapter : ArrayAdapter<Any?> {
constructor(context: Context, resource: Int) : super(context, resource)
constructor(context: Context, resource: Int, objects: Array<out Any?>) : super(context, resource, objects)
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults? {
return null
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {}
}
}
}
usage:
val adapter = NoFilterArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, items)
Upvotes: 5
Reputation: 364421
Currently there is a open bug on this topic.
You can use as workaround the setFreezesText
method:
AutoCompleteTextView autoCompleteTextView =
view.findViewById(R.id.offering_details_type_dropdown);
autoCompleteTextView.setFreezesText(false);
The EditText
set 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.
Upvotes: 5
Reputation: 1217
Like @Gabriele Mariotti mentioned, it's a bug. As mentioned in the posted link, I did this workaround which works well:
public class ExposedDropDown extends MaterialAutoCompleteTextView {
public ExposedDropDown(@NonNull final Context context, @Nullable final AttributeSet attributeSet) {
super(context, attributeSet);
}
@Override
public boolean getFreezesText() {
return false;
}
}
Upvotes: 0