使用ArrayAdapter上的过滤器过滤带有多个TextView的自定义ListView <t implements =“”parcelable =“”>

时间:2017-05-03 18:07:51

标签: android listview android-arrayadapter parcelable android-filter

我有一个班级class CustomAdapter extends ArrayAdapter<CustomListItem>,其中CustomListItem implements Parcelable,并且有3个字符串变量(String a, b, c;

加载ListView时,一切都按预期工作。但是,现在我想使用我的SearchView仅显示包含用户输入文本的列表元素。我希望CustomAdapter中的Filter查看该文本的a,b和c,并显示包含该文本的任何列表项。

因此,例如,如果用户键入“ar”,并且abc是"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();
                }
            }
        };
    }
}

但这不起作用,可能是因为我不知道自己在做什么。这是CustomListItem:

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();
            }
        };
    }
}

1 个答案:

答案 0 :(得分:2)

publishResults方法中:

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }

您没有将适配器上的过滤结果设置为在数据集无效之前显示的新数据集。此外,您还应保留原始值的副本,因此如果他们清空查询,您可以保留并重置原始结果。

编辑框架示例代码: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/widget/ArrayAdapter.java#ArrayAdapter.ArrayFilter