listview过滤item(基于ArrayAdapter和BaseAdapter)

2019-02-21 11:16:00 浏览数 (1)

1.基于ArrayAdapter的过滤

ArrayAdapter有个专门的函数用于过滤getFilter,所以只需要运用这个函数就行

代码语言:javascript复制
        private String[] item = { "1", "2", "3", "4", "5" };

        editText1 = (EditText) findViewById(R.id.editText1);
        listView1 = (ListView) findViewById(R.id.listView1);
        adapter1 = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, item);
        listView1.setAdapter(adapter1);

        editText1.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
                adapter1.getFilter().filter(s.toString());
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

但是很多时候我们不可能用ArrayAdapter这么简单的适配器,更多的时候是要继承BaseAdapter

2.基于BaseAdapter的过滤

网上其实也有相关的解决方案,但是只告诉你怎么做,却没告诉你原理。今天我来展示一下怎么做。 其实我们也可以仿照ArrayAdapter的getFilter函数自己写一个,那么我们就有必要去看一下源码

代码语言:javascript复制
    //返回过滤器
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }

    private class ArrayFilter extends Filter {
        //performFiltering函数执行过滤操作,也就是过滤的规则是什么
        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            //FilterResults 是过滤后放置结果的容器,他有两个参数,values 存放结果集,count 存放长度。具体可看源码
            FilterResults results = new FilterResults();

            if (mOriginalValues == null) {
                synchronized (mLock) {
                    mOriginalValues = new ArrayList<T>(mObjects);
                }
            }

            //这一部分就是过滤规则的显示,不难,就是过滤出以prefix开头的元素
            if (prefix == null || prefix.length() == 0) {
                ArrayList<T> list;
                synchronized (mLock) {
                    list = new ArrayList<T>(mOriginalValues);
                }
                results.values = list;
                results.count = list.size();
            } else {
                String prefixString = prefix.toString().toLowerCase();

                ArrayList<T> values;
                synchronized (mLock) {
                    values = new ArrayList<T>(mOriginalValues);
                }

                final int count = values.size();
                final ArrayList<T> newValues = new ArrayList<T>();

                for (int i = 0; i < count; i  ) {
                    final T value = values.get(i);
                    final String valueText = value.toString().toLowerCase();

                    // First match against the whole, non-splitted value
                    if (valueText.startsWith(prefixString)) {
                        newValues.add(value);
                    } else {
                        final String[] words = valueText.split(" ");
                        final int wordCount = words.length;

                        // Start at index 0, in case valueText starts with space(s)
                        for (int k = 0; k < wordCount; k  ) {
                            if (words[k].startsWith(prefixString)) {
                                newValues.add(value);
                                break;
                            }
                        }
                    }
                }

                results.values = newValues;
                results.count = newValues.size();
            }

            return results;
        }

        //将过滤后的结果通过mObjects返回并且显示,查看整个源文件你会发现里面有两个List<T>。一个就是保存原本的数据,一个是过滤后的数据,也就是这个mObjects。getItem等函数返回的也是mObjects的长度
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mObjects = (List<T>) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    }

看懂以上代码。那么arrayadapter的源码也基本看懂,那么接下来我们也来自己做一个

代码语言:javascript复制
    class MyAdapter extends BaseAdapter {
        private MyFilter mFilter;
        //必须存放两个String[]类型数据,一个保存原始数据,一个用来展示过滤后的数据
        private String[] item;
        private String[] displayItem;

        public MyAdapter(Context context, String[] item) {
            super();
            this.item = item;
            displayItem = item;
        }

        //因为要展示的是过滤后的数据,所以是displayItem的一些属性
        @Override
        public int getCount() {
            return displayItem.length;
        }

        @Override
        public String getItem(int position) {
            return displayItem[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                convertView = new TextView(MainActivity.this);
            }
            ((TextView)convertView).setText(displayItem[position]);
            return convertView;
        }

        //返回过滤器
        public MyFilter getFilter() {
            if (mFilter == null) {
                mFilter = new MyFilter();
            }
            return mFilter;
        }

        class MyFilter extends Filter {

            @Override
            protected FilterResults performFiltering(CharSequence prefix) {
                FilterResults results = new FilterResults();

                if (prefix == null || prefix.length() == 0) {
                    results.values = item;
                    results.count = item.length;
                } else {
                    String prefixString = prefix.toString();

                    final ArrayList<String> newValues = new ArrayList<String>();

                    for (int i = 0; i < item.length; i  ) {
                        final String value = item[i];
                        if (value.equals(prefixString)) {//我这里的规则就是筛选出和prefix相同的元素
                            newValues.add(value);
                        }
                    }

                    results.values = (String[]) newValues
                            .toArray(new String[newValues.size()]);
                    results.count = newValues.size();
                }

                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint,
                    FilterResults results) {
                displayItem = (String[]) results.values;
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        }
    }

好了,接下来就可以用getFilter().filter()函数来过滤了,是不是很简单呢???

0 人点赞