How to add a custom adapter to an AutoCompleteTextView
Here Code is working for me,
Set This adapter to autocompletetextview
AutoCompleteTextView etProductSearch = (AutoCompleteTextView)getView().findViewById(R.id.edtSearchBoxTakeOrder);ProductSearchAdapter adapter = new ProductSearchAdapter(getActivity(), android.R.layout.simple_dropdown_item_1line, productList);etProductSearch.setAdapter(adapter );
ProductSearchAdapter class
import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.Filter;import android.widget.TextView;public class ProductSearchAdapter extends ArrayAdapter<ProductDataModel> { private ArrayList<ProductDataModel> items; private ArrayList<ProductDataModel> itemsAll; private ArrayList<ProductDataModel> suggestions; private int viewResourceId; @SuppressWarnings("unchecked") public ProductSearchAdapter(Context context, int viewResourceId, ArrayList<ProductDataModel> items) { super(context, viewResourceId, items); this.items = items; this.itemsAll = (ArrayList<ProductDataModel>) items.clone(); this.suggestions = new ArrayList<ProductDataModel>(); this.viewResourceId = viewResourceId; } public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(viewResourceId, null); } ProductDataModel product = items.get(position); if (product != null) { TextView productLabel = (TextView) v.findViewById(android.R.id.text1); if (productLabel != null) { productLabel.setText(product.getProductName()); } } return v; } @Override public Filter getFilter() { return nameFilter; } Filter nameFilter = new Filter() { public String convertResultToString(Object resultValue) { String str = ((ProductDataModel) (resultValue)).getProductName(); return str; } @Override protected FilterResults performFiltering(CharSequence constraint) { if (constraint != null) { suggestions.clear(); for (ProductDataModel product : itemsAll) { if (product.getProductName().toLowerCase() .startsWith(constraint.toString().toLowerCase())) { suggestions.add(product); } } FilterResults filterResults = new FilterResults(); filterResults.values = suggestions; filterResults.count = suggestions.size(); return filterResults; } else { return new FilterResults(); } } @Override protected void publishResults(CharSequence constraint, FilterResults results) { @SuppressWarnings("unchecked") ArrayList<ProductDataModel> filteredList = (ArrayList<ProductDataModel>) results.values; if (results != null && results.count > 0) { clear(); for (ProductDataModel c : filteredList) { add(c); } notifyDataSetChanged(); } } };}
According to the documentation, the inferred type of setAdapter in AutoCompleteTextView is :
<T extends ListAdapter & Filterable> void setAdapter(T adapter)
Your adapter must be a ListAdapter (which BaseAdapter is, so far so good) and a Filterable, which BaseAdapter is not, nor is your Adapter implementation. I would extend an ArrayAdapter, which is Filterable, not to mention is would simplify your implementation (some of your methods duplicate methods of ArrayAdapter for the same result) :
public class TwoLineDropdownAdapter extends ArrayAdapter<TwoLineDropDown> { private LayoutInflater mInflater = null; private Activity activity; public TwoLineDropdownAdapter(Activity a, ArrayList<TwoLineDropDown> items) { super(a, 0, items); activity = a; mInflater = (LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public static class ViewHolder { public TextView title; public TextView description; } public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.dropdown_text_twoline, parent, false); holder.title = (TextView) convertView .findViewById(R.id.text1); holder.description = (TextView) convertView .findViewById(R.id.text2); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } return convertView; }}
Converted Dwivedi Ji's answer to Kotlin. I had some issue with Android Studio's auto convert. Thus, spent some time to make it work.
Now it is working. In case anyone needs it (in my case, I am filtering street names):
class StreetsAdapter( private val mContext: Context, private val viewResourceId: Int, private val items: ArrayList<Street>) : ArrayAdapter<Street?>(mContext, viewResourceId, items.toList()) { private val itemsAll = items.clone() as ArrayList<Street> private var suggestions = ArrayList<Street>() override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { var v: View? = convertView if (v == null) { val vi = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater v = vi.inflate(viewResourceId, null) } val street: Street? = items[position] if (street != null) { val streetTitle = v?.findViewById(R.id.tvStreetTitle) as TextView? streetTitle?.text = street.title } return v!! } override fun getFilter(): Filter { return nameFilter } private var nameFilter: Filter = object : Filter() { override fun convertResultToString(resultValue: Any): String { return (resultValue as Street).title } override fun performFiltering(constraint: CharSequence?): FilterResults { return if (constraint != null) { suggestions.clear() for (street in itemsAll) { if (street.title.toLowerCase().startsWith(constraint.toString().toLowerCase())) { suggestions.add(street) } } val filterResults = FilterResults() filterResults.values = suggestions filterResults.count = suggestions.size filterResults } else { FilterResults() } } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { val filteredList = results?.values as ArrayList<Street>? if (results != null && results.count > 0) { clear() for (c: Street in filteredList ?: listOf<Street>()) { add(c) } notifyDataSetChanged() } } }}
And set your adapter:
val adapter = StreetsAdapter(this, R.layout.item_street, //Your layout. Make sure it has [TextView] with id "tvStreetTitle" arrayListOf() //Your list goes here)autoTextView.threshold = 1 //will start working from first characterautoTextView.setAdapter(adapter)