Android在AutoCompleteTextView中输入字母或者汉字通过Filterable实现自动筛选提醒

最近项目中需要优化搜索功能,在AutoCompleteTextView快速输入字母或者汉字以及快速删除会导致莫名的崩溃,接手别人半路的项目,当时就日狗了,只能改了。下面先上 AutoCompleteTextView 布局代码,其实特别简单。

<AutoCompleteTextView
            android:id="@+id/search_main"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:hint="输入想要搜索的内容"
            android:textSize="6pt"
            android:maxLines="1"
            android:paddingTop="5dp"
            android:paddingBottom="5dp"
            android:paddingLeft="5dp"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"/>

下面就是Activity里面找到控件进行初始化操作。

search_main = (AutoCompleteTextView) findViewById(R.id.search_main);
search_main.setAdapter(new mAdapter());
search_main.setOnItemClickListener(new AdapterView
                .OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int
                    position, long id) {
            }
        });
//输入一个字母就开始自动提示
search_main.setThreshold(1);

初始化完成后就可以通过Filterable实现自动筛选提醒,这也是最重要的部分,就是因为上个离职的人把筛选过后的数据和原始数据用的同一个ArrayList,所以才会在AutoCompleteTextView快速输入字母或者汉字以及快速删除会导致莫名的崩溃,下面直接上代码块。

private HanyuPinyinOutputFormat format;//汉语拼音搜索
private List<String> mList;//原始数据源
private ArrayList<String> mOriginalValues;//筛选过后的全新数据源
private final Object mLock = new Object();//同步锁不太懂。

class ViewHolder {
        TextView title;
        TextView text;
    }

    //我们需要在继承的BaseAdapter的基础上再实现Filterable接口的getFilter方法,同时在Adapter内部写一个继承Filter的内部类来完成过滤功能
    class mAdapter extends BaseAdapter implements Filterable {

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public Object getItem(int position) {
            return mList.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            } else {
                convertView = LayoutInflater.from(SearchActivity.this).inflate
                        (R.layout.map_search,
                                parent, false);
                holder = new ViewHolder();
                holder.title = (TextView) convertView.findViewById(R.id.title);
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            }

holder.title.setText(mList.get(position));         holder.text.setText(infoList.get(position).address);
         return convertView;
        }

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


        class ArrayFilter extends Filter {

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
// 持有过滤操作完成之后的数据。该数据包括过滤操作之后的数据的值以及数量。
                FilterResults results = new FilterResults();
                if (mOriginalValues == null) {
                    synchronized (mLock) {
                    //保存原始数据
                        mOriginalValues = new ArrayList<String>(mList);
                    }
                }

                if (constraint == null || constraint.length() == 0) {
                    synchronized (mLock) {
                        results.values = mOriginalValues;
                        results.count = mOriginalValues.size();
                    }
                } else {
                    List<String> resultList = new ArrayList<>();
                    String str = constraint.toString().toLowerCase();
                    for (String s : mOriginalValues) {
                        if (getStringPinYin(s).contains(str) || s.contains
                                (str) || getPinYinHeadChar(s)
                                .equalsIgnoreCase(str) || getPinYinHeadChar
                                (s).toLowerCase().contains(str.toLowerCase())) {
                            resultList.add(s);
                        }
                    }
                    results.values = resultList;
                    results.count = resultList.size();
                }
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults
                    results) {
                mList = (List<String>) results.values;//更新适配器的数据
                if (results.count > 0) {
                    notifyDataSetChanged();//通知数据发生了改变
                } else {
                    notifyDataSetInvalidated();//通知数据失效
                }
            }
        }
    }

    public String getPinYinHeadChar(String str) {
        String convert = "";
        for (int j = 0; j < str.length(); j++) {
            char word = str.charAt(j);
            // 提取汉字的首字母
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
            if (pinyinArray != null) {
                convert += String.valueOf(pinyinArray[0].charAt(0))
                        .toUpperCase();
            } else {
                convert += String.valueOf(word).toUpperCase();
            }
        }
        return convert;
    }

    public String getStringPinYin(String str) {
        StringBuilder sb = new StringBuilder();
        String tempPinyin = null;
        for (int i = 0; i < str.length(); ++i) {
            tempPinyin = getCharacterPinYin(str.charAt(i));
            if (tempPinyin == null) {
                // 如果str.charAt(i)非汉字,则保持原样
                sb.append(str.charAt(i));
            } else {
                sb.append(tempPinyin);
            }
        }
        return sb.toString();
    }

    public String getCharacterPinYin(char c) {
        format = new HanyuPinyinOutputFormat();
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        try {
            pinyin = PinyinHelper.toHanyuPinyinStringArray(c, format);
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        // 如果c不是汉字,toHanyuPinyinStringArray会返回null
        if (pinyin == null) return null;
        // 只取一个发音,如果是多音字,仅取第一个发音
        return pinyin[0];
    }

上面代码中的汉字拼音筛选用到的是第三方包,可以在as中如下引入

compile files('libs/pinyin4j-2.5.0.jar')

到这就可以实现输入汉字,拼音首字母进行搜索,在这里可能会看的不太懂,怪我太菜,下面上搜索出来的效果图。

搜索后的数据

本人菜鸟一枚,勿喷,这篇博客写的不好,多担待。

下面附上自己写好的demo地址
下载链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值