最近项目中需要优化搜索功能,在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地址
下载链接