My app has an AutoCompleteTextView that queries a Room database and displays the search results in the dropdown as the user types. The results are displayed correctly but the dropdown's height is always too large for the number of items (see screenshot below).
Basically the AutoCompleteTextView has a TextWatcher that sends the current text to the ViewModel, which in turn queries the database. Once the results are received, the ViewModel updates the view state (a Flow) and the fragment, which observes it, reassigns the AutoCompleteTextView's adapter with the new data.
Dropdown item layout
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/spacing_8">
<GridLayout
android:id="@+id/imageContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
... />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/txtName"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="wrap_content"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment layout
<com.google.android.material.textfield.TextInputLayout>
...
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/spacing_16"/>
</com.google.android.material.textfield.TextInputLayout>
Adapter
internal class StationAdapter(
context: Context,
private val stations: List<UiStation>
) : ArrayAdapter<String>(
context,
R.layout.item_station,
stations.map { it.name }
) {
fun getStation(position: Int): UiStation = stations[position]
override fun getCount(): Int = stations.size
override fun getItem(position: Int): String = stations[position].name
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
return convertView ?: run {
val inflater = LayoutInflater.from(context)
val binding = ItemStationBinding.inflate(inflater, parent, false).apply {
val station = stations[position]
imageContainer.addIconsForModes(station.modes)
txtName.text = station.name
}
binding.root
}
}
...
}
Fragment
private fun handleState(state: StationSearchViewState) = with(state) {
...
stations?.let {
val adapter = StationAdapter(
context = requireContext(),
stations = it
)
binding.autoCompleteTextView.setAdapter(adapter)
}
}
Now these are the other things I tried as well but didn't work (got the same result):
- Passing all of the database table's results to the adapter and implementing a custom filter
- Implementing a function to submit new data to the adapter and calling
notifyDataSetChanged()
- Setting the AutoCompleteTextView's
android:dropDownHeight
property towrap_content
The only thing that seems to work is when I use an ArrayAdapter
with the android.R.layout.simple_list_item_1
layout for the items