Reputation: 13555
I am working on a listview filter, that means, there is a editbox, if I type in some keywords , the listview data will change accordingly. To begin with, there is a dataset.
private ArrayList<PostItem> postList;
Assuming the list is already fill with data, here is the adapter with filtering:
private class PostAdapter extends ArrayAdapter<PostItem> implements
Filterable {
public PostAdapter(Context context, int resource, List<PostItem> items) {
super(context, resource, items);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.post_item, parent, false);
}
PostItem post = getItem(position);
if (post != null) {
TextView title = (TextView) v.findViewById(R.id.postTitle);
TextView date = (TextView) v.findViewById(R.id.postDate);
v.setTag(post.id);
title.setText(Html.fromHtml(post.title));
date.setText(post.name + " "
+ getResources().getString(R.string.post_on) + " "
+ post.date);
}
return v;
}
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
ArrayList<PostItem> filteredList = (ArrayList<PostItem>)results.values;
clear();
for (PostItem item :filteredList) {
add(item);
}
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
ArrayList<PostItem> filteredArray = new ArrayList<PostItem>();
constraint = constraint.toString().toLowerCase();
for (PostItem item : postList) {
if (item.title.toLowerCase().contains(constraint)) {
filteredArray.add(item);
}
}
results.count = filteredArray.size();
results.values = filteredArray;
return results;
}
};
return filter;
}
}
The problem is , clear() function will also remove all the item contains in postList and insert all the latest filtered result. How to fix it? I tried to have a copied variable e.g. copyPostList = postList
but still the same. Thanks for helping
Update: More explanation:
First, The postList has item "abc";
Then, Type in "ab", the list show "abc", which is correct
After that, Type in "xyz", the list show nothing, which is correct
Finally, Type in "abc", the list show nothing, which is incorrect
Upvotes: 0
Views: 2391
Reputation: 13555
Final code , add the filtering and getView for my case
private class PostAdapter extends ArrayAdapter<PostItem> implements Filterable {
private ArrayList<PostItem> fullList;
private ArrayList<PostItem> mOriginalValues;
private ArrayFilter mFilter;
public PostAdapter(Context context, int resource, List<PostItem> objects) {
super(context, resource, objects);
fullList = (ArrayList<PostItem>) objects;
mOriginalValues = new ArrayList<PostItem>(fullList);
}
@Override
public void add(PostItem object) {
super.add(object);
fullList.add(object);
mOriginalValues.add(object);
}
@Override
public void clear() {
super.clear();
fullList.clear();
mOriginalValues.clear();
}
@Override
public int getCount() {
return fullList.size();
}
@Override
public PostItem getItem(int position) {
return fullList.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.post_item, parent, false);
}
PostItem post = getItem(position);
if (post != null) {
TextView title = (TextView) v.findViewById(R.id.postTitle);
TextView date = (TextView) v.findViewById(R.id.postDate);
v.setTag(post.id);
title.setText(Html.fromHtml(post.title));
date.setText(post.name + " "
+ getResources().getString(R.string.post_on) + " "
+ post.date);
}
return v;
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
ArrayList<PostItem> list = new ArrayList<PostItem>();
if (mOriginalValues == null) {
mOriginalValues = new ArrayList<PostItem>(fullList);
}
for (PostItem item : mOriginalValues) {
if (item.title.toLowerCase().contains(prefix.toString().toLowerCase())) {
list.add(item);
}
}
results.values = list;
results.count = list.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
fullList = (ArrayList<PostItem>) results.values;
} else {
fullList = new ArrayList<PostItem>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
Thanks for helping
Upvotes: 0
Reputation: 3305
public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> fullList;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
public AutoCompleteAdapter(Context context, int resource, List<String> objects) {
super(context, resource, objects);
fullList = (ArrayList<String>) objects;
mOriginalValues = new ArrayList<String>(fullList);
}
@Override
public void add(String object) {
super.add(object);
fullList.add(object);
mOriginalValues.add(object);
}
@Override
public void clear() {
super.clear();
fullList.clear();
mOriginalValues.clear();
}
@Override
public int getCount() {
return fullList.size();
}
@Override
public String getItem(int position) {
return fullList.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setEllipsize(TextUtils.TruncateAt.START);
return view;
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
mOriginalValues = new ArrayList<String>(fullList);
}
ArrayList<String> list = new ArrayList<String>(mOriginalValues);
results.values = list;
results.count = list.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
fullList = (ArrayList<String>) results.values;
} else {
fullList = new ArrayList<String>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
Check it out. this adapter works great. Good luck.
Upvotes: 3