Reputation: 1040
I have the following ArrayAdapter:
class SearchAdapter(private val activity: Activity, private var species: ArrayList<Specie>) : ArrayAdapter<Specie>(activity, R.layout.specie_item, species) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
return convertView ?: createView(position, parent)
}
private fun createView(position: Int, parent: ViewGroup?): View {
val specie = species[position]
val view = LayoutInflater.from(context).inflate(R.layout.specie_item, parent, false)
view.specie_text.text = specie.name
return view
}
override fun getCount() = species.size
override fun getItem(position: Int) = species[position]
override fun getFilter() = filter
private var filter: Filter = object : Filter() {
override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
val results = FilterResults()
val query = if (constraint != null && constraint.isNotEmpty()) autocomplete(constraint.toString())
else arrayListOf()
results.values = query
results.count = query.size
return results
}
private fun autocomplete(input: String): ArrayList<Specie> {
val results = arrayListOf<Specie>()
for (specie in species) {
if (specie.name.toLowerCase().contains(input.toLowerCase())) results.add(specie)
}
return results
}
override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults) {
if (results.count > 0) notifyDataSetChanged()
else notifyDataSetInvalidated()
}
override fun convertResultToString(result: Any) = (result as Specie).name
}
}
The purpose of this adapter is to show some suggestions when we type something in a AutoCompleteTextview. To do this, I have a filter that search for species names according to the user input. The problem is that this filter is not working as I expected:
Until here it's fine. It his showing all species names that start with agro
But after typing something more, it is not filtering anymore. It should show species names that start with agrostis cas, but it is still showing the Agrostis azorica.
Is my filter bad? I have tried some other ways to filter, but I got exactly the same result.
Upvotes: 2
Views: 2145
Reputation: 1206
What you are missing currently is your adapter does not take into account anything about your filter, you set it to depend on the full species list with your get count, getItemPosition.
Also you should take care of updating your text when views are recycled by your adapter and not set the value only when views are created.
Something like that should be better :
class SearchAdapter(private val activity: Activity, private var species: ArrayList<Specie>) : ArrayAdapter<Specie>(activity, R.layout.specie_item, species) {
var filtered = ArrayList<Specie>()
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
return convertView ?: createView(position, parent)
}
private fun createView(position: Int, parent: ViewGroup?): View {
val view = LayoutInflater.from(context).inflate(R.layout.specie_item, parent, false)
view?.name?.text = filtered[position].name
return view
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View {
convertView ?: LayoutInflater.from(context).inflate(R.layout.specie_item, parent, false)
convertView?.name?.text = filtered[position].name
return super.getDropDownView(position, convertView, parent)
}
override fun getCount() = filtered.size
override fun getItem(position: Int) = filtered[position]
override fun getFilter() = filter
private var filter: Filter = object : Filter() {
override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
val results = FilterResults()
val query = if (constraint != null && constraint.isNotEmpty()) autocomplete(constraint.toString())
else arrayListOf()
results.values = query
results.count = query.size
return results
}
private fun autocomplete(input: String): ArrayList<Specie> {
val results = arrayListOf<Specie>()
for (specie in species) {
if (specie.name.toLowerCase().contains(input.toLowerCase())) results.add(specie)
}
return results
}
override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults) {
filtered = results.values as ArrayList<Specie>
notifyDataSetInvalidated()
}
override fun convertResultToString(result: Any) = (result as Specie).name
}
}
Upvotes: 2