Reputation: 71
I am doing a search filter using filterable. I manage to get the search result when I search by keyword but the listview is empty after the first search. I want it to show all the data when the user input is null.
This is the code I edited. Now I cannot get any search result. Any idea which part still wrong?
public class ProductListAdapter extends BaseAdapter implements Filterable {
private Context context;
private int layout;
private ArrayList<Booth> productList= new ArrayList<>();
private ArrayList<Booth> tempList = new ArrayList<>();
private ValueFilter mFilter = new ValueFilter();
public ProductListAdapter(Context context, int layout, ArrayList<Booth> productList) {
this.context = context;
this.layout = layout;
this.productList = productList;
this.tempList = productList;
}
@Override
public int getCount() {
return tempList.size();
}
public void addItems(ArrayList<Booth> items) {
productList.addAll(items);
tempList.addAll(items);
notifyDataSetChanged();
}
@Override
public Object getItem(int position) {
return tempList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(
int position, View view, ViewGroup viewGroup) {
Typeface face_02 = Typeface.createFromAsset(context.getAssets(), "customfont/grb.otf");
ViewHolder holder = new ViewHolder();
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(layout, null);
holder.Boothname = (TextView) view.findViewById(R.id.Boothname);
holder.Rating = (TextView) view.findViewById(R.id.Rating);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
Booth product = productList.get(position);
holder.Boothname.setText(product.getBoothName());
holder.Rating.setText(product.getRating());
holder.Rating.setTypeface(face_02);
holder.Boothname.setTypeface(face_02);
return view;
}
@Override
public Filter getFilter() {
return mFilter;
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Booth> filterList = new ArrayList<Booth>();
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < productList.size(); i++) {
if ((productList.get(i).getBoothName().toLowerCase())
.contains(constraint.toString().toLowerCase())) {
Booth boothdata = new Booth(productList.get(i)
.getBoothName(), productList.get(i)
.getRating());
filterList.add(boothdata);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = productList.size();
results.values = productList;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
tempList = (ArrayList<Booth>) results.values;
notifyDataSetChanged();
}
}
class ViewHolder {
TextView Boothname, Rating;
}
}
Upvotes: 0
Views: 2421
Reputation: 8200
yes, you got this error. Why? Because after searchings, from times to times, your productList loses its product. So, how to resolve it? You should make filter data
for filtering only and you will search in the filter data
instead of your productList
as below:
filterList = new List<Product>()// do clone here when you set new data to your list.
// then in the performFiltering(), use filterList instead.
for (int i = 0; i < filterList.size(); i++) {
if ((filterList.get(i).getBoothName().toLowerCase())
.startsWith(constraint.toString().toLowerCase())) {
Booth boothdata = new Booth(filterList.get(i)
.getBoothName(), filterList.get(i)
.getRating());
filterList.add(boothdata);
}
}
This is what you should do.
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
productList = (ArrayList<Booth>) results.values; // if you use templist here, there's no change in getView
notifyDataSetChanged();
}
Upvotes: 1
Reputation: 886
This is happened because you are updating your original list when user search anything.You have to use tempList which is hold temporary data and used to show search result,it is also used to shows list initially.And ProductList contains original list and it is used to compare with the search string.
Initialize variable
private List<Booth> productList=new ArrayList<>(); //you have already done this,this contains original list
private List<Booth> tempList=new ArrayList<>(); //add this one is to show search result
Method for the add data should be like this:
public void addItems(List<Booth> items) {
productList.addAll(items);
tempList.addAll(items);
notifyDataSetChanged();
}
Method for the remove data should be like this:
public void removeItems(){
productList.clear();
tempList.clear();
}
getItem and getCount method should be like this:
@Override
public int getCount() {
return tempList.size();
}
@Override
public Booth getItem(int position) {
return tempList.get(position);
}
ValueFilter should be like this:
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
//filter list as a local variable
ArrayList<Booth> filterList = new ArrayList<Booth>();
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < productList.size(); i++) {
if ((productList.get(i).getBoothName().toLowerCase())
.startsWith(constraint.toString().toLowerCase())) {
Booth boothdata = new Booth(productList.get(i)
.getBoothName(), productList .get(i)
.getRating());
filterList.add(boothdata);
}
}
results.count = filterList.size();
results.values = filterList;
Log.e("VALUES", results.values.toString());
} else {
results.count = productList.size();
results.values = productList;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
tempList = (ArrayList<Booth>) results.values;
notifyDataSetChanged();
}
}
Upvotes: 1