【发布时间】:2017-05-03 18:07:50
【问题描述】:
我有一个类class CustomAdapter extends ArrayAdapter<CustomListItem>,其中CustomListItem implements Parcelable,并且有3个字符串变量(String a, b, c;)
加载 ListView 时一切正常。但是,现在我想使用我的 SearchView 仅显示包含用户输入文本的列表元素。我希望来自 CustomAdapter 的过滤器查看该文本的 a、b 和 c,并显示包含该文本的任何列表项。
因此,例如,如果用户键入“ar”,并且 a b c 是"Rome", "Male", "Arnold",则无论哪个内容在哪个变量中,因为其中一个具有“Ar”(我不希望它是大小写敏感)我希望该项目显示在列表中。
目前,这个过滤器业务让我很困惑,stackoverflow 中的自定义过滤器似乎有很多答案,但我找不到具有我所描述的那种行为的答案。到目前为止,这就是我所拥有的:
public class CustomAdapter extends ArrayAdapter<CustomListItem> {
public CustomAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
public CustomAdapter(Context context, int resource, List<CustomListItem> 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.row_layout, null);
}
CustomListItem s = getItem(position);
if (s != null) {
TextView a = (TextView) v.findViewById(R.id.a);
TextView b = (TextView) v.findViewById(R.id.b);
TextView c = (TextView) v.findViewById(R.id.c);
if (a != null) {
a.setText(s.getA());
}
if (b != null) {
b.setText(s.getB());
}
if (c != null) {
c.setText(s.getC());
}
}
return v;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults result = new FilterResults();
List<CustomListItem> list = new ArrayList<>();
int max = getCount();
for (int cont = 0; cont < max; cont++) {
if (constraint != null) {
CustomListItem item = getItem(cont);
boolean contains =
item.getA().toLowerCase().contains(constraint) ||
item.getB().toLowerCase().contains(constraint) ||
item.getC().toLowerCase().contains(constraint);
if (contains) {
list.add(getItem(cont));
}
} else {
list.add(getItem(cont));
}
}
result.values = list;
result.count = list.size();
return result;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}
}
但这不起作用,可能是因为我不知道自己在做什么。这是自定义列表项:
public class CustomListItem implements Parcelable {
private String a, b, c;
public CustomListItem(String a, String b, String c) {
this.a = a;
this.b = b;
this.c = c;
}
private CustomListItem(Parcel in) {
a = in.readString();
b = in.readString();
c = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(a);
dest.writeString(b);
dest.writeString(c);
}
public String getA() {
return a;
}
public String getB() {
return b;
}
public String getC() {
return c;
}
@Override
public int describeContents(){
return 0;
}
public static final Parcelable.Creator<CustomListItem> CREATOR
= new Parcelable.Creator<CustomListItem>() {
public CustomListItem createFromParcel(Parcel in) {
return new CustomListItem(in);
}
public CustomListItem[] newArray(int size) {
return new CustomListItem[size];
}
};
}
我在我的 AppCompatActivity 类中添加这样的过滤器:
SearchView searchView = (SearchView) findViewById(R.id.searchView);
final CustomAdapter adapter = new CustomAdapter(getApplicationContext(), R.layout.row_layout, item_list); //item_list is my list of custom items, defined elsewhere
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String text) {
adapter.getFilter().filter(text);
return true;
}
@Override
public boolean onQueryTextChange(String text) {
adapter.getFilter().filter(text);
return true;
}
});
我相信我的代码唯一有问题的是 getFilter() 方法,所以我正在寻找的答案是实现我刚才所说的正确而干净的方法。我也会很高兴解释我做错了什么,以及一些例子。感谢您的宝贵时间!
解决方案:
根据 Submersed 的回答,我进行了必要的更改以使代码正常工作。正如预期的那样,问题仅限于过滤器。但是,由于我更改了 CustomAdapter 类中的其他内容以实现我的解决方案,因此这是整个固定类:
public class CustomAdapter extends ArrayAdapter<CustomListItem> {
private final List<CustomListItem> mList;
public CustomAdapter(Context context, int resource, List<CustomListItem> items) {
super(context, resource, items);
mList = new ArrayList<>(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.row_layout, null);
}
CustomListItem s = getItem(position);
if (s != null) {
TextView a = (TextView) v.findViewById(R.id.a);
TextView b = (TextView) v.findViewById(R.id.b);
TextView c = (TextView) v.findViewById(R.id.c);
if (a != null) {
a.setText(s.getA());
}
if (b != null) {
b.setText(s.getB());
}
if (c != null) {
c.setText(s.getC());
}
}
return v;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults result = new FilterResults();
String constraint = charSequence.toString().toLowerCase();
if (constraint == null || constraint.isEmpty()) {
result.values = mList;
result.count = mList.size();
} else {
List<CustomListItem> list = new ArrayList<>();
int max = mList.size();
for (int cont = 0; cont < max; cont++) {
CustomListItem item = mList.get(cont);
boolean contains =
item.getA().toLowerCase().contains(constraint) ||
item.getB().toLowerCase().contains(constraint) ||
item.getC().toLowerCase().contains(constraint);
if (contains) {
list.add(mList.get(cont));
}
}
result.values = list;
result.count = list.size();
}
return result;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
clear();
addAll((ArrayList<CustomListItem>) results.values);
notifyDataSetChanged();
}
};
}
}
【问题讨论】:
标签: android listview android-arrayadapter parcelable android-filter