Reputation: 1589
I am facing an issue in AutoCompleteTextView
adapter. I have to create autocomplete adapter which will display the filtered contact list from the device. In my case, the filtering is working fine. But when I select an item from the list, the data set in the AutoCompleteTextView
is from the original list, not from the filtered list. Can any one help me to resolve the issue?
Please find my adapter class below
class ContactListAdapter(private var ctx: Context, private var contacts: ArrayList<MobileContact>):
ArrayAdapter<MobileContact>(ctx, R.layout.contact_item, contacts) {
private var filter: ContactFilter? = null
private class ViewHolder(view: View?) {
var name: TextView? = null
var number: TextView? = null
init {
name = view?.findViewById(R.id.contactName)
number = view?.findViewById(R.id.contactNumber)
}
}
private val filteredContacts = ArrayList<MobileContact>()
override fun getCount() = filteredContacts.size
override fun getFilter(): Filter {
return if(filter == null)
ContactFilter(this, contacts)
else filter!!
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view: View
val viewHolder: ViewHolder
val contact = filteredContacts[position]
val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
if(convertView == null) {
view = inflater.inflate(R.layout.contact_item, parent, false)
viewHolder = ViewHolder(view)
view.tag = viewHolder
} else {
view = convertView
viewHolder = view.tag as ViewHolder
}
viewHolder.name?.text = contact.name
viewHolder.number?.text = contact.number
return view
}
@Suppress("UNCHECKED_CAST")
class ContactFilter(private var adapter: ContactListAdapter, private var contacts: ArrayList<MobileContact>) : Filter() {
private var filteredContacts = ArrayList<MobileContact>()
override fun performFiltering(constraint: CharSequence?): FilterResults {
filteredContacts.clear()
val results = FilterResults()
if(constraint == null || constraint.isEmpty()) {
filteredContacts.addAll(contacts)
} else {
val filterPattern = constraint.toString().toLowerCase(Locale.ENGLISH).trim()
for(contact in contacts) {
if(contact.name.toLowerCase(Locale.ENGLISH).contains(filterPattern) ||
contact.number.contains(filterPattern)) {
filteredContacts.add(contact)
}
}
}
results.values = filteredContacts
results.count = filteredContacts.size
return results
}
override fun convertResultToString(resultValue: Any?): CharSequence {
return (resultValue as MobileContact).number
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
adapter.filteredContacts.clear()
adapter.filteredContacts.addAll(results?.values as ArrayList<MobileContact>)
adapter.notifyDataSetChanged()
}
}
}
Upvotes: 0
Views: 156
Reputation: 1589
After a lot of debugging, I resolved the issue. Here what I did is I removed the filtered results from the adapter. And the filter will be kept the whole data.
Please find the code below. Someone may have useful
class ContactListAdapter(private var ctx: Context, private var contacts: ArrayList<MobileContact>):
ArrayAdapter<MobileContact>(ctx, R.layout.contact_item, contacts) {
private var filter = ContactFilter()
private class ViewHolder(view: View?) {
var name: TextView? = null
var number: TextView? = null
init {
name = view?.findViewById(R.id.contactName)
number = view?.findViewById(R.id.contactNumber)
}
}
override fun getCount() = contacts.size
override fun getFilter(): Filter {
return filter
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view: View
val viewHolder: ViewHolder
val contact = contacts[position]
val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
if(convertView == null) {
view = inflater.inflate(R.layout.contact_item, parent, false)
viewHolder = ViewHolder(view)
view.tag = viewHolder
} else {
view = convertView
viewHolder = view.tag as ViewHolder
}
viewHolder.name?.text = contact.name
viewHolder.number?.text = contact.number
return view
}
@Suppress("UNCHECKED_CAST")
inner class ContactFilter : Filter() {
private var filteredContacts = ArrayList<MobileContact>()
private var origList = ArrayList<MobileContact>()
override fun performFiltering(constraint: CharSequence?): FilterResults {
if(origList.isEmpty())
origList.addAll(contacts)
filteredContacts.clear()
val results = FilterResults()
if(constraint == null || constraint.isEmpty()) {
filteredContacts.addAll(origList)
} else {
val filterPattern = constraint.toString().toLowerCase(Locale.ENGLISH).trim()
for(contact in origList) {
if(contact.name.toLowerCase(Locale.ENGLISH).contains(filterPattern) ||
contact.number.contains(filterPattern)) {
filteredContacts.add(contact)
}
}
}
results.values = filteredContacts
results.count = filteredContacts.size
return results
}
override fun convertResultToString(resultValue: Any?): CharSequence {
return (resultValue as MobileContact).number
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
contacts.clear()
contacts.addAll(results?.values as ArrayList<MobileContact>)
notifyDataSetChanged()
}
}
}
Upvotes: 0