实现ListView过滤功能最方便的便是使用ArrayAdapter,里面自带的getFilter()方法能很方便的实现此功能,然而实际中更多是使用自定义的Adapter 继承自BaseAdapter,然后继承BaseAdapter不能像ArrayAdapter那样直接通过ListView的setTextFilter()就对ListView进行简单的过滤,我们需要去手动实现一个Filterable接口,自定义过滤规则;
1.首先创建一个Adapter继承自BaseAdapter
public class ComplainListAdapter extends BaseAdapter implements Filterable {
private List<ComplainListBean> mList;//这个数据会改变的
private List<ComplainListBean> backData;//用于备份原始数据
private LayoutInflater mInflater;
MyFilter mFilter;
public ComplainListAdapter(Context context, List<ComplainListBean> data) {
mList = data;
mInflater = LayoutInflater.from(context);
backData = data;
}
然后重写BaseAdapter的方法,这里就不贴出代码。
2.然后实现Filterable接口的方法
//当ListView调用setTextFilter()方法的时候,便会调用该方法
public Filter getFilter() {
if (mFilter == null) {
mFilter = new MyFilter();
}
return mFilter;
}
class MyFilter extends Filter {
/**
* 这个方法是定义过滤规则
* <p>Invoked in a worker thread to filter the data according to the
* constraint. Subclasses must implement this method to perform the
* filtering operation. Results computed by the filtering operation
* must be returned as a {@link FilterResults} that
* will then be published in the UI thread through
* {@link #publishResults(CharSequence,
* FilterResults)}.</p>
* <p/>
* <p><strong>Contract:</strong> When the constraint is null, the original
* data must be restored.</p>
*
* @param constraint the constraint used to filter the data
* @return the results of the filtering operation
* @see #filter(CharSequence, FilterListener)
* @see #publishResults(CharSequence, FilterResults)
* @see FilterResults
*/
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<ComplainListBean> list;
if (TextUtils.isEmpty(constraint)) {//当过滤关键词未空我们显示所有数据
list = backData;
} else {//否则把符合的数据对象添加到集合中
list = new ArrayList<>();
for (ComplainListBean mComplainListBean : backData) {
//设置过滤的关键词 if(mComplainListBean.getTitle().contains(constraint)||mComplainListBean.getContent().contains(constraint)||mComplainListBean.getDate().contains(constraint))
{
Log.d("performFiltering:",mComplainListBean.toString());
list.add(mComplainListBean);
}
}
}
results.values = list;//将得到的集合保存到FilterResult 的value变量中
results.count = list.size();//将集合的大小保存到FilterResult的count变量中
return results;
}
/**
* 在这个方法中告诉适配器更新了界面
* <p>Invoked in the UI thread to publish the filtering results in the
* user interface. Subclasses must implement this method to display the
* results computed in {@link #performFiltering}.</p>
*
* @param constraint the constraint used to filter the data
* @param results the results of the filtering operation
* @see #filter(CharSequence, FilterListener)
* @see #performFiltering(CharSequence)
* @see FilterResults
*/
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mList = (List<ComplainListBean>) results.values;
Log.d("publishResults",""+results.count);
if(results.count>0){
//当数据发生改变
notifyDataSetChanged();
Log.d("publishResults","notifyDataSetChanged");
}else{
//当数据没有改变
notifyDataSetInvalidated();
Log.d("publishResults","notifyDataSetInvalidated");
}
}
}
3.然后在主函数onPostExecute (这里ListView用的是异步加载)中添加Search view的监听事件
protected void onPostExecute(List<ComplainListBean> complainListBeen) {
super.onPostExecute(complainListBeen);
ComplainListAdapter mAdapter = new ComplainListAdapter(ComplainListActivity.this, complainListBeen);
mListView.setAdapter(mAdapter);
//打开过滤功能
mListView.setTextFilterEnabled(true);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
//搜索文本为空时,过滤设置
mListView.clearTextFilter();
} else {
//设置过滤关键字
mListView.setFilterText(newText);
}
return true;
}
});
}
}
这就可以根据关键词实现搜索