2015-10-29

[Android] an Text search Adapter for AppCompatAutoCompleteTextView or AutoCompleteTextView

這是一個可以自動完成的TextView(AutoCompleteTextView)所需要的Adapter

原本的ArrayAdapter的自動完成只會搜尋到以已輸入的字串為開頭的字串。
(因為ArraryAdapter的Filter是用startWith去找字串)
例如:List當中有"安全"、"安心"、"保安"、"偏安"、"討厭"
輸入"安",只會搜尋出"安全"、"安心"
而"保安"、"偏安"就搜尋不到
"討厭"也是一樣搜尋不到

以下這個改寫過的Adapter則是只要有包含已輸入的字串都會顯示出來。
例如:List當中有"安全"、"安心"、"保安"、"偏安"、"討厭"
輸入"安",會搜尋出所有有"安"的String"安全"、"安心"、"保安"、"偏安"
而"討厭"裡面沒有"安"所以就搜尋不到



Usage:
AppCompatAutoCompleteTextView mAutoCompleteText;
List<String> list;

// find view by id
// ...

mAutoCompleteText.setAdapter(new AutoCompleteAdapter(getContext(),
            android.R.layout.simple_spinner_item, list));






class AutoCompleteAdapter extends ArrayAdapter {

        private final ArrayList mList;

        private AutoCompleteFilter mFilter;

        public AutoCompleteAdapter(Context context, int resource, List list) {
            super(context, resource, list);
            this.mList = Lists.newArrayList(list);
        }

        @Override public Filter getFilter() {
            if (mFilter == null) {
                mFilter = new AutoCompleteFilter();
            }
            return mFilter;
        }

        private class AutoCompleteFilter extends Filter {

            @Override protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                final ArrayList resultList;
                if (constraint == null || constraint.length() == 0) {
                    resultList = Lists.newArrayList(mList);
                } else {
                    String searchString = constraint.toString().toLowerCase();
                    resultList = Lists.newArrayList();
                    for (T value : mList) {
                        if (value.toString().toLowerCase().contains(searchString)) {
                            resultList.add(value);
                        }
                    }
                }
                results.values = resultList;
                results.count = resultList.size();
                return results;
            }

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

        }

    }