原创文章,如有转载,请注明出处: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,大功告成!
欢迎关注我的公众号,和我一起每天进步一点点!