material-components-android
material-components-android copied to clipboard
[MaterialAutoCompleteTextView] Default item layout not available with ExposedDropdownMenu for ArrayAdapters
Is your feature request related to a problem? Please describe.
When we set the items of MaterialAutoCompleteTextView on the XML with
<com.google.android.material.textfield.MaterialAutoCompleteTextView
app:simpleItems="@array/customer_types"
We can see a color change of the selected item when the dropdown menu is shown.
If we set the items with an ArrayAdapter as
val customerTypes = resources.getStringArray(R.array.customer_types)
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, customerTypes)
arrayAdapter.setAdapter(adapter)
The coloring of the selected item is not working. I've tried many available item layouts and none worked as the default. I looked at the code and I saw these lines
simpleItemLayout =
attributes.getResourceId(
R.styleable.MaterialAutoCompleteTextView_simpleItemLayout,
R.layout.mtrl_auto_complete_simple_item);
As far as I can see this is not available to use.
Describe the solution you'd like
Able to give the layout to an ArrayAdapter so that the selected item can be colored ( there is already XML for the color of the selected simpleItemSelectedColor
)
Describe alternatives you've considered
I've tried to create my item layouts, however, I couldn't see any of the state_???
are helpful for the background drawable. Is it possible to write this behavior?
@kelalaka153 can you try using app:simpleItemLayout
on the MaterialAutoCompleteTextView
to pass in your custom layout instead of making your own adapter?
@dsn5ft How will this solve my issue? The default layout is fine for me, however, the items are not ready at the compile time. So, I need to use an Array Adapter. Ok, now I found the solution for the Array of Strings
sampleDropDown.setSimpleItems(customerTypes)
I still wonder how can I write a similar layout and use the default layout in ArrayAdapter. The above solution still requires overriding toString
for complex data types and I need to get the ID from the object, not the non-unique string.
How will this solve my issue? The default layout is fine for me, however, the items are not ready at the compile time. So, I need to use an Array Adapter. Ok, now I found the solution for the Array of Strings
Based on your original question, I wasn't sure if the issue was that you wanted a different layout or if you needed to use a programmatic API. setSimpleItems
was going to be my next suggestion.
I still wonder how can I write a similar layout and use the default layout in ArrayAdapter. The above solution still requires overriding toString for complex data types and I need to get the ID from the object, not the non-unique string.
The "simple item" APIs are meant for quick and straightforward use cases. At some point with more advanced use cases (custom layouts, complex data types, etc.) it might be better to just implement your own adapter/layout.
Re: toString
, if you don't want to override toString
on your main class, I would suggest making a new model class (e.g., CustomerTypeItem) for the items where you can override toString
specifically for this use case, and then convert your customerTypes
list into a customerTypeItems
which you can pass to setSimpleItems
.
@dsn5ft Thanks for the response. That is one way to solve the toString issue.
I used an interface. Another one is using the selected index to access the ID from the original data, however, a custom layout still has the problem of how will I color the selected item. I tested it in various states for the background with a drawable and none worked.
So my original issues remains;
- solve the coloring issue of the selected item when not using the default layout with setSimpleItems
- and, find the name of the default item layout!
Glad to hear the toString issue is resolved.
I'm confused about the custom layout need and exactly what you are trying to accomplish, because before you mentioned The default layout is fine for me, however, the items are not ready at the compile time.
Can you explain more about why you can't use setSimpleItems and the default layout?
Another one is using the selected index to access the ID from the original data
Each item model class can hold a reference to the original class, correct? E.g.:
data class CustomerTypeItem(val customerType: CustomerType) {
override fun toString(): String {
// return...
}
}
So you can look up the original data by index, something like:
autoCompleteTextView.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val item = parent.getItemAtPosition(position) as CustomerTypeItem
// access original data via item.customerType
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
@dsn5ft Thanks again. If I'm using an extension then I can use setSimpleItems. However, considering that in some cases I will need to display more than a string, I must somehow show the highlighted selected item as the default item layout did. I'd tried the default states, however, I couldn't figure out how to work it. selected, checked, enabled, etc. That is why I'm wondering about the default layout's implementation.
Ah ok. The source of our adapter which handles the selected item is here:
https://github.com/material-components/material-components-android/blob/c8b9b1c0bb8e51501246c902073acc45aedeebd6/lib/java/com/google/android/material/textfield/MaterialAutoCompleteTextView.java#L539
However now I am thinking about a way to allow changing the default layout to a more complex one while keeping the rest of the "simple item" behavior.
@dsn5ft are we on the same page about onItemSelectedListener? In my project, OnItemSelectedListener
comes from AdapterView.OnItemSelectedListener
and it doesn't respond to the events. I've found a serious bug on MaterialAutoCompleteTextView when android:inputType="textAutoComplete"
. trying to post it.
Also, this one state that this listener remains silent https://stackoverflow.com/a/61703032/1820553
Ah I meant OnItemClickListener
:
https://stackoverflow.com/a/9250218