I've the Custom CustomerAdapter
public class CustomerAdapter extends ArrayAdapter<Customer> {
private final String MY_DEBUG_TAG = "CustomerAdapter";
private ArrayList<Customer> items;
private int viewResourceId;
public CustomerAdapter(Context context, int viewResourceId, ArrayList<Customer> items) {
super(context, viewResourceId, items);
this.items = items;
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);
}
Customer customer = items.get(position);
if (customer != null) {
TextView customerNameLabel = (TextView) v.findViewById(R.id.customerNameLabel);
if (customerNameLabel != null) {
customerNameLabel.setText(String.valueOf(customer.getName()));
}
}
return v;
}
}
and customer_auto
layout
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/customerNameLabel"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:padding="10dp" android:textSize="16sp"
android:textColor="#000">
</TextView>
and on my public void onCreate
AutoCompleteTextView customerAutoComplete = (AutoCompleteTextView) findViewById(R.id.autocomplete_customer);
CustomerAdapter customerAdapter = new CustomerAdapter(this, R.layout.customer_auto, customerList);
customerAutoComplete.setAdapter(customerAdapter);
and Customer.java
public class Customer implements Parcelable {
private int id;
private String name = "";
public Customer() {
// TODO Auto-generated constructor stub
}
/**
* This will be used only by the MyCreator
*
* @param source
*/
public Customer(Parcel source) {
/*
* Reconstruct from the Parcel
*/
id = source.readInt();
name = source.readString();
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public Customer createFromParcel(Parcel source) {
return new Customer(source);
}
@Override
public Customer[] newArray(int size) {
return new Customer[size];
// TODO Auto-generated method stub
}
};
@Override
public String toString() {
return this.name;
}
}
But the auto suggest box does not filter correctly. for eg; if i type an
in the test box customers starting with br
are showing up!
I have to over-ride the getFilter() method of the Adapter
Here is the code which worked for me, thanks to sacoskun
public class CustomerAdapter extends ArrayAdapter<Customer> {
private final String MY_DEBUG_TAG = "CustomerAdapter";
private ArrayList<Customer> items;
private ArrayList<Customer> itemsAll;
private ArrayList<Customer> suggestions;
private int viewResourceId;
public CustomerAdapter(Context context, int viewResourceId, ArrayList<Customer> items) {
super(context, viewResourceId, items);
this.items = items;
this.itemsAll = (ArrayList<Customer>) items.clone();
this.suggestions = new ArrayList<Customer>();
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);
}
Customer customer = items.get(position);
if (customer != null) {
TextView customerNameLabel = (TextView) v.findViewById(R.id.customerNameLabel);
if (customerNameLabel != null) {
// Log.i(MY_DEBUG_TAG, "getView Customer Name:"+customer.getName());
customerNameLabel.setText(customer.getName());
}
}
return v;
}
@Override
public Filter getFilter() {
return nameFilter;
}
Filter nameFilter = new Filter() {
@Override
public String convertResultToString(Object resultValue) {
String str = ((Customer)(resultValue)).getName();
return str;
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
if(constraint != null) {
suggestions.clear();
for (Customer customer : itemsAll) {
if(customer.getName().toLowerCase().startsWith(constraint.toString().toLowerCase())){
suggestions.add(customer);
}
}
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) {
ArrayList<Customer> filteredList = (ArrayList<Customer>) results.values;
if(results != null && results.count > 0) {
clear();
for (Customer c : filteredList) {
add(c);
}
notifyDataSetChanged();
}
}
};
}
This is my solution. I feel like it's a bit cleaner (doesn't use 3 separate, confusing ArrayLists) than the accepted one, and has more options. It should work even if the user types backspace, because it doesn't remove the original entries from mCustomers
(unlike the accepted answer):
public class CustomerAdapter extends ArrayAdapter<Customer> {
private LayoutInflater layoutInflater;
List<Customer> mCustomers;
private Filter mFilter = new Filter() {
@Override
public String convertResultToString(Object resultValue) {
return ((Customer)resultValue).getName();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null) {
ArrayList<Customer> suggestions = new ArrayList<Customer>();
for (Customer customer : mCustomers) {
// Note: change the "contains" to "startsWith" if you only want starting matches
if (customer.getName().toLowerCase().contains(constraint.toString().toLowerCase())) {
suggestions.add(customer);
}
}
results.values = suggestions;
results.count = suggestions.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
clear();
if (results != null && results.count > 0) {
// we have filtered results
addAll((ArrayList<Customer>) results.values);
} else {
// no filter, add entire original list back in
addAll(mCustomers);
}
notifyDataSetChanged();
}
};
public CustomerAdapter(Context context, int textViewResourceId, List<Customer> customers) {
super(context, textViewResourceId, customers);
// copy all the customers into a master list
mCustomers = new ArrayList<Customer>(customers.size());
mCustomers.addAll(customers);
layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = layoutInflater.inflate(R.layout.customerNameLabel, null);
}
Customer customer = getItem(position);
TextView name = (TextView) view.findViewById(R.id.customerNameLabel);
name.setText(customer.getName());
return view;
}
@Override
public Filter getFilter() {
return mFilter;
}
}
Instead of overriding getFilter()
method in adapter, simply we can override the toString()
of the userDefined object (Customer).
In toString()
just return the field based on what you need to filter. It worked for me.
In my example I'm filtering based on names:
public class Customer{
private int id;
private String name;
@Override
public String toString() {
return this.name;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With