Android搜索功能的实现

原创文章,如有转载,请注明出处:http://blog.csdn.net/myth13141314/article/details/72961087


这里的搜索功能旨在解决本地数据搜索过滤,实现是EditText + ListView。

  • ListView用于展示数据,
  • EditText用于接受输入内容,通过输入内容来过滤ListView中的数据并重新展示
  • 过滤的实现用的是android.widget包下的Filter类,以及Filterable接口

具体实现

  • 首先介绍Filter的实现
  • 主要是复写performFiltering方法和publishResults方法
  • performFiltering方法主要是实现过滤的规则
  • publishResults方法主要是返回过滤后的结果以及更新数据
  • 这里的过滤规则很简单,就是用String的contains方法,包含过滤词的数据都会过滤出来,但是不能过滤拼音输入的过滤,这个需要利用第三方拼音库
class MyFilter extends Filter {
        // 创建集合保存原始数据
        private List<String> original = new ArrayList<String>();

        public MyFilter(List<String> list) {
            this.original = list;
        }

        /**
         * 该方法返回搜索过滤后的数据
         */
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            // 创建FilterResults对象
            FilterResults results = new FilterResults();

            /**
             * 没有搜索内容的话就还是给results赋值原始数据的值和大小
             * 执行了搜索的话,根据搜索的规则过滤即可,最后把过滤后的数据的值和大小赋值给results
             *
             */
            if(TextUtils.isEmpty(constraint)){
                results.values = original;
                results.count = original.size();
            }else {
                // 创建集合保存过滤后的数据
                List<String> mList = new ArrayList<String>();
                // 遍历原始数据集合,根据搜索的规则过滤数据
                for(String s: original){
                    // 过滤规则的具体实现
                    if(s.trim().toLowerCase().contains(constraint.toString().trim().toLowerCase())){
                        // 规则匹配的话就往集合中添加该数据
                        mList.add(s);
                    }
                }
                results.values = mList;
                results.count = mList.size();
            }

            return results;
        }

        /**
         * 该方法用来刷新用户界面,根据过滤后的数据重新展示列表
         */
        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) {
            // 获取过滤后的数据
            list = (List<String>) results.values;
            // 如果接口对象不为空,那么调用接口中的方法获取过滤后的数据,具体的实现在new这个接口的时候重写的方法里执行
            if(listener != null){
                listener.getFilterData(list);
            }
            // 刷新数据源显示
            notifyDataSetChanged();
        }
    }
  • ListView的Adapter修改
public class ProjectAdapter extends BaseAdapter implements Filterable{

    private List<String> list;
    private Context context;
    private MyFilter filter = null;// 创建MyFilter对象
    private FilterListener listener;

    public ProjectAdapter(List<String> list, Context context, FilterListener listener) {
        this.list = list;
        this.context = context;
        this.listener = listener;
    }

    ...

    //Filterable接口的实现
    @Override
    public Filter getFilter() {
        // 如果MyFilter对象为空,那么重写创建一个
        if (filter == null) {
            filter = new MyFilter(list);
        }
        return filter;
    }

    ...

}
  • FilterListener
public interface FilterListener {

    void getFilterData(List<String> list);// 获取过滤后的数据

}

使用

  • 为ListView生成Adapter
ProjectAdapter projectAdapter = new ProjectAdapter(names, getContext(), new FilterListener() {
    @Override
    public void getFilterData(List<String> list) {
        //对返回的过滤数据进行处理,这里的names肯定是变了
        //然后设置点击监听事件
        setOnItemClick(list);
    }
});
  • EditText获取输入的过滤信息
etSearch.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) {
        if (projectAdapter != null) {
            projectAdapter.getFilter().filter(s);
        }
    }

    @Override
    public void afterTextChanged(Editable s) {

    }
});
  • 以上就是搜索功能的简单实现

若要支持输入拼音进行过滤,可以使用第三方拼音库来处理拼音输入,然后过滤规则里增加对拼音的支持即可

这里介绍下pinyin4j库的使用
  • 引入项目
compile 'com.belerweb:pinyin4j:2.5.0'//获取汉字拼音
  • 编写一个拼音的处理工具类CN2SpellUtil
public class CN2SpellUtil {

    public static StringBuffer sb = new StringBuffer();

    /**
     * 获取汉字字符串的首字母,英文字符不变
     * 例如:阿飞→af
     */
    public static String getPinYinHeadChar(String chines) {
        sb.setLength(0);
        char[] chars = chines.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] > 128) {
                try {
                    sb.append(PinyinHelper.toHanyuPinyinStringArray(chars[i], defaultFormat)[0].charAt(0));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                sb.append(chars[i]);
            }
        }
        return sb.toString();
    }

    /**
     * 获取汉字字符串的第一个字母
     */
    public static String getPinYinFirstLetter(String str) {
        sb.setLength(0);
        char c = str.charAt(0);
        String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
        if (pinyinArray != null) {
            sb.append(pinyinArray[0].charAt(0));
        } else {
            sb.append(c);
        }
        return sb.toString();
    }

    /**
     * 获取汉字字符串的汉语拼音,英文字符不变
     */
    public static String getPinYin(String chines) {
        sb.setLength(0);
        char[] nameChar = chines.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < nameChar.length; i++) {
            if (nameChar[i] > 128) {
                try {
                    sb.append(PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0]);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                sb.append(nameChar[i]);
            }
        }
        return sb.toString();
    }
}
  • 然后在上面的Adapter的过滤规则里加上对拼音的支持
// 过滤规则的具体实现
if(s.trim().toLowerCase().contains(constraint.toString().trim().toLowerCase()) 
|| CN2SpellUtil.getPinYin(s).contains(constraint.toString().trim().toLowerCase())){
    // 规则匹配的话就往集合中添加该数据
    mList.add(s);
}
  • OK,大功告成!


欢迎关注我的公众号,和我一起每天进步一点点!
这里写图片描述

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值