1. 程式人生 > >listview過濾item(基於ArrayAdapter和BaseAdapter)

listview過濾item(基於ArrayAdapter和BaseAdapter)

1.基於ArrayAdapter的過濾

ArrayAdapter有個專門的函式用於過濾getFilter,所以只需要運用這個函式就行

        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函式自己寫一個,那麼我們就有必要去看一下原始碼

    //返回過濾器
    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的原始碼也基本看懂,那麼接下來我們也來自己做一個

    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()函式來過濾了,是不是很簡單呢???