-
目标 Adapter可以适配AutoCompleteTextView实现模糊查询自动补全功能,相比简陋的 ArrayAdapter而言,SimpleAdapter可实现布局功能更加复杂的任务,但 SimpleAdapter并不能实现我们自己想要的筛选方式,所以我们可继承SimpleAdapter 实现自定义过滤器的Adapter。
-
效果
- 实现策略
1、 自定义Adapter
由于SimpleAdapter复杂布局功能足够强大,所以只需要继承SimpleAdapter即可,无
需从头继承BaseAdapter并实现Filterable接口。在继承SimpleAdapter后,首先要
重写getFilter()方法。该方法返回一个内部过滤器类Filter。
public Filter getFilter() {
if (mFilter == null) {
mFilter = new MySmipleFilter();
}
return mFilter;
}
getFilter()方法供AutoCompleteTextView调用。
private AutoCompleteTextView acv;
acv = findViewById(R.id.acv);
acv.setAdapter(mySimpleAdapter);
#AutoCompleteTextView源码
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
if (mObserver == null) {
mObserver = new PopupDataSetObserver(this);
} else if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
if (mAdapter != null) {
//noinspection unchecked
mFilter = ((Filterable) mAdapter).getFilter();
adapter.registerDataSetObserver(mObserver);
} else {
mFilter = null;
}
mPopup.setAdapter(mAdapter);
}
所以我们必须要在自定义Adapter中实现一个继承自Filter类的内部类,并重写其中的
两个最重要的方法performFiltering(CharSequence prefix)和
publishResults(CharSequence constraint, FilterResults results)。前者中完成自定义的
模糊查询过滤规则(写我们的业务逻辑代码);后者主要负责过滤后数据条目的刷新显
示,切记不能使用mData = results.values;这样会使mData的引用对象发生变化,导致
Adapter绑定数据始终是原始数据,不能刷新成功。所以要在mData原内存中改变数
据。
private class MySmipleFilter extends Filter{
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mUnfilteredData == null) {
mUnfilteredData = new ArrayList<Map<String, ?>>(mData);
}
if (prefix == null || prefix.length() == 0) {
ArrayList<Map<String, ?>> list = mUnfilteredData;
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;
int count = unfilteredValues.size();
ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);
#自定义筛选逻辑
for (int i = 0; i < count; i++) {
Map<String, ?> h = unfilteredValues.get(i);
if (h != null) {
int len = mTo.length;
String words = (String)h.get(mFrom[1]);
if (words.toLowerCase().contains(prefixString)) {
newValues.add(h);
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
#切记不能使用mData = results.values;这样会使mData的引用对象发生变化,导致Adapter
绑定数据始终是原始数据,不能刷新成功。所以要在mData原内存中改变数据。
mData.clear();
List<Map<String, Object>> mData_ = (List<Map<String, Object>>) results.values;
mData.addAll(mData_);
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
2、设置监听器
为了实现点击后自动补全功能,要为AutoCompleteTextView设置监听器实现补全自定
义的信息。
acv.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id)->
{
Map<String, Object> mdata = (Map<String, Object>)mySimpleAdapter.getItem(position);
Object s = mdata.get("文本介绍");
acv.setText(s.toString());
});