如何使用AutoCompleteTextView,并自定義過濾規則

AutoCompleteTextView特性

  • AutoCompleteTextView是EditText的子類,可以使用EditText所有的屬性
  • 用于輸入框的自動完成提示,非常適合搜索框。
  • setThreshold:指定用戶至少輸入幾個字符才會顯示提示

常規的簡單實現

  • 設置AutoCompleteTextView的適配器為ArrayAdapter,ArrayAdapter已經實現了Filterable接口。此時,只要給AutoCompleteTextView添加文字監聽:

private String[] autostr = new String[] { "a", "ab", "abc",  
        "abcd", "b", "bc", "bcd" }; 


//android.R.layout.simple_dropdown_item_1line是系統自帶的簡單item布局
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,  
              android.R.layout.simple_dropdown_item_1line, autostr);

 mAutoCompleteTv.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                //只需添加這一句代碼即可
                //這句話的意思是為AutoCompleteTextView設置過濾字段為s,只要數據是以s開頭,都會顯示出來
                adapter.getFilter().filter(s);
            }

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

自定義過濾規則

  • 要自己定義過濾規則,主要是對Filterable接口的實現,其他部分與ListView的適配器設置并無區別。

  • 下面給出一個實例,實現的效果是:在輸入框輸入字符串s,只要某條數據里含有s,就將該條數據顯示出來。關鍵代碼如下。


相關變量
-------------------------------------------------------------------------------------------------
    private AutoCompleteTextView mAutoCompleteTv;

    //這個一旦賦值就不會改變了,相當數據庫的概念,是搜索的數據源,也就是說展示的list數據是根據定義
    //的過濾規則,從mSearchDataBaseList中取出符合過濾規則的數據。
    //這個mSearchDataBaseList一般是從后臺獲取。
    private List<String> mSearchDataBaseList = new ArrayList<>();
    
    //這個是搜索的結果集合,隨搜索內容而改變
    private List<String> mSearchResultList = new ArrayList<>();//
    
    private MyAutoCompleteTvAdapter mAutoCompleteTvAdapter;


設置適配器
---------------------------------------------------------------------------------------
    mAutoCompleteTvAdapter = new MyAutoCompleteTvAdapter(getApplicationContext(), mSearchResultList);
    mAutoCompleteTv.setAdapter(mAutoCompleteTvAdapter);


適配器的具體實現
-----------------------------------------------------------------------------------------
    class MyAutoCompleteTvAdapter extends BaseAdapter implements Filterable {

        private Context context;
        //該list存放的是最終彈出列表的數據
        private List<String> list = new ArrayList<>();

        private MyAutoCompleteTvAdapter(Context context, List<String> list) {
            this.context = context;
            this.list = list;
        }

        @Override
        public Filter getFilter() {
            Filter filter = new Filter() {
                /**
                 * 在后臺線程執行,定義過濾算法
                 * @param constraint :就是你在輸入框輸入的字符串
                 * @return 符合條件的數據結果,會在下面的publishResults方法中將數據傳給list
                 */
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {

                    FilterResults results = new FilterResults();

                    if (constraint == null || constraint.length() == 0) {
                        //
                        results.values = mSearchDataBaseList;
                        results.count = mSearchDataBaseList.size();
                    } else {

                        //這個newList是實際搜索出的結果集合,實際上是將該newList的數據賦給了list
                        List<String> newList = new ArrayList<>();
                        for (String s : mSearchDataBaseList) {
                            //包含就添加到newList中
                            if (s.contains(constraint.toString().trim()
                            )) {
                                newList.add(s);
                            }
                        }

                        //將newList傳給results
                        results.values = newList;
                        results.count = newList.size();
                        newList = null;
                    }

                    return results;
                }

                /**
                 * 本方法在UI線程執行,用于更新自動完成列表
                 * @param constraint  
                 * @param results
                 */
                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {

                    if (results != null && results.count > 0) {//有符合過濾規則的數據
                        list.clear();
                        list.addAll((List<String>) results.values);
                        notifyDataSetChanged();
                    } else {//沒有符合過濾規則的數據
                        notifyDataSetInvalidated();
                    }
                }

                /**
                 * 將符合條件的數據轉換為你想要的方式,一般無需實現
                 * 控制用戶點擊提示時要填充至輸入框的文本內容。
                 */
                @Override
                public CharSequence convertResultToString(Object resultValue) {

                   return super.convertResultToString(resultValue);
                    //假如這里寫 return "啊哈哈";
                    //那么,無論你點擊哪個條目,出現在輸入框的永遠是"啊哈哈"這幾個字。
                }
            };

            return filter;
        }

        @Override
        public int getCount() {
            return list != null && list.size() > 0 ? list.size() : 0;
        }

        /**
         * 這里必須返回list.get(position),否則點擊條目后輸入框顯示的是position,而非該position的數據
         *
         * @param position
         * @return
         */
        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

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

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            TvViewHolder holder;
            if (convertView == null) {
                convertView = View.inflate(context, R.layout.item_autocompletetv_simple_dropdown, null);
                holder = new TvViewHolder();
                holder.tv = (TextView) convertView.findViewById(R.id.text1);
                convertView.setTag(holder);

            } else {
                holder = (TvViewHolder) convertView.getTag();
            }

            //注意這里不要為convertView添加點擊事件,默認是點擊后:①下拉窗收起;
            //②點擊的條目數據會顯示在搜索框中;③光標定位到字符串末位。
            //如果自己添加點擊事件,就要首先實現上面的①、②、③。
            holder.tv.setText(list.get(position));
            return convertView;
        }

        class TvViewHolder {
            TextView tv;
        }
    }

布局文件,很簡單,只有一個textview
------------------------------------------------------------------------------------------------
    <?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/text1"
          style="?android:attr/dropDownItemStyle"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="?android:attr/listPreferredItemHeight"
          android:ellipsize="marquee"
          android:padding="12dp"
          android:singleLine="true"
          android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
          android:textColor="#8e8d8d"/>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,076評論 25 708
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,510評論 0 17
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,754評論 18 399
  • 打,打死這個婊子”上官婉兒,“啊,555555”張晴晴,“他媽的,誰叫的老師,快走,婉兒”李倩。 張晴晴,一名高一...
    壁花圣人閱讀 276評論 0 0
  • 扣女嚕嚕嚕 啦咯啦咯了幾個個咯啦咯啦咯啦咯
    NeroLeung閱讀 193評論 0 0