Android搜索功能的实现

来源:互联网 发布:java孤傲苍狼 博客园 编辑:程序博客网 时间:2024/05/17 01:03

原创文章,如有转载,请注明出处: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,大功告成!
原创粉丝点击