How to add a custom adapter to an AutoCompleteTextView How to add a custom adapter to an AutoCompleteTextView android android

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)