How To Add A Custom Adapter To An Autocompletetextview
Solution 1:
Here Code is working for me,
Set This adapter to autocompletetextview
AutoCompleteTextViewetProductSearch= (AutoCompleteTextView)getView().findViewById(R.id.edtSearchBoxTakeOrder);
ProductSearchAdapteradapter=newProductSearchAdapter(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;
publicclassProductSearchAdapterextendsArrayAdapter<ProductDataModel> {
private ArrayList<ProductDataModel> items;
private ArrayList<ProductDataModel> itemsAll;
private ArrayList<ProductDataModel> suggestions;
privateint viewResourceId;
@SuppressWarnings("unchecked")publicProductSearchAdapter(Context context, int viewResourceId,
ArrayList<ProductDataModel> items) {
super(context, viewResourceId, items);
this.items = items;
this.itemsAll = (ArrayList<ProductDataModel>) items.clone();
this.suggestions = newArrayList<ProductDataModel>();
this.viewResourceId = viewResourceId;
}
public View getView(int position, View convertView, ViewGroup parent) {
Viewv= convertView;
if (v == null) {
LayoutInflatervi= (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(viewResourceId, null);
}
ProductDataModelproduct= items.get(position);
if (product != null) {
TextViewproductLabel= (TextView) v.findViewById(android.R.id.text1);
if (productLabel != null) {
productLabel.setText(product.getProductName());
}
}
return v;
}
@Overridepublic Filter getFilter() {
return nameFilter;
}
FilternameFilter=newFilter() {
public String convertResultToString(Object resultValue) {
Stringstr= ((ProductDataModel) (resultValue)).getProductName();
return str;
}
@Overrideprotected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
suggestions.clear();
for (ProductDataModel product : itemsAll) {
if (product.getProductName().toLowerCase()
.startsWith(constraint.toString().toLowerCase())) {
suggestions.add(product);
}
}
FilterResultsfilterResults=newFilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
} else {
returnnewFilterResults();
}
}
@OverrideprotectedvoidpublishResults(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();
}
}
};
}
Solution 2:
According to the documentation, the inferred type of setAdapter in AutoCompleteTextView is :
<T extendsListAdapter & Filterable> voidsetAdapter(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) :
publicclassTwoLineDropdownAdapterextendsArrayAdapter<TwoLineDropDown> {
privateLayoutInflatermInflater=null;
private Activity activity;
publicTwoLineDropdownAdapter(Activity a, ArrayList<TwoLineDropDown> items) {
super(a, 0, items);
activity = a;
mInflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
publicstaticclassViewHolder {
public TextView title;
public TextView description;
}
public View getView(finalint position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = newViewHolder();
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;
}
}
Solution 3:
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):
classStreetsAdapter( privateval mContext: Context,
privateval viewResourceId: Int,
privateval items: ArrayList<Street>) : ArrayAdapter<Street?>(mContext, viewResourceId, items.toList()) {
privateval itemsAll = items.clone() as ArrayList<Street>
privatevar suggestions = ArrayList<Street>()
overridefungetView(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!!
}
overridefungetFilter(): Filter {
return nameFilter
}
privatevar nameFilter: Filter = object : Filter() {
overridefunconvertResultToString(resultValue: Any): String {
return (resultValue as Street).title
}
overridefunperformFiltering(constraint: CharSequence?): FilterResults {
returnif (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()
}
}
overridefunpublishResults(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 character
autoTextView.setAdapter(adapter)
Solution 4:
I believe that the easiest approach is to extend SimpleAdapter
.
publicclassMyAdapterextendsandroid.widget.SimpleAdapter {
staticArrayList<Map<String, String>> toMapList(Collection<MyObject> objectsCollection) {
ArrayList<Map<String, String>> objectsList = newArrayList<Map<String, String>>(objectsCollection.size());
for (MyObject obj : objectsCollection) {
Map<String, String> map = newHashMap<String, String>();
map.put("name", obj.getName());
map.put("details", obj.getDetails());
objectsList.add(map);
};
return objectsList;
}
publicMyAdapter(Context context, Collection<MyObject> objects) {
super(context, toMapList(objects),
R.layout.auto_complete_layout, newString[] {"name", "description"}, new int[] {R.id.name, R.id.description});
}
}
The major drawback is that this will bring candidates based on any space-delimited word in either name or description. If you add another field to your auto_complete_layout
, it will be involved in matching, too.
Therefore, I finished with rewriting the SimpleAdapter to better fit my needs, removing a significant amount of the base class overhead which was not relevant for my use case. But the few lines above give you a good start, and provide a solid reference to start customization from.
Solution 5:
Always keep in mind that when you are customizing ArrayAdapter for your AutoCompleteTextView, you have to implement your own filtering method.
Post a Comment for "How To Add A Custom Adapter To An Autocompletetextview"