Android实现ListView过滤功能之继承BaseAdap
2019-03-27 本文已影响0人
老子爱吃荷包蛋
作者:zml_2015
原文:https://blog.csdn.net/zml_2015/article/details/52082174
实现ListView过滤功能最方便的便是使用ArrayAdapter,里面自带的getFilter()方法能很方便的实现此功能
但是在实际的开发中,ArrayAdapter有的时候满足不了我们项目的各种需求,所以一般都是继承于BaseAdapter,然后继承BaseAdapter不能像ArrayAdapter那样直接通过ListView的setTextFilter()就对ListView进行简单的过滤,我们需要去手动实现一个Filterable接口,自定义过滤规则;
效果图
image.png image.png
接下来直接上代码了
- 首先是布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
>
<LinearLayout
android:id="@+id/search_top_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@color/blue_title_bg"
android:gravity="center_vertical"
android:orientation="horizontal" >
<com.zml.collrec.view.AutoClearEditText
android:id="@+id/search_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/search_box"
android:drawableRight="@drawable/app_icon_voice"
android:focusable="true"
android:hint="搜索"
android:padding="6dp"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="@dimen/micro_text_size" />
<ImageButton
android:id="@+id/search_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#035AB2"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:src="@mipmap/android_search_icon" />
</LinearLayout>
<ListView
android:id="@+id/search_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/search_top_layout"
android:divider="@null"
android:dividerHeight="1dp"
android:listSelector="@null"
android:scrollbars="none"
/>
</LinearLayout>
布局视图
image.png
* SearchFragment.java
/**
* @author郑明亮 @email 1072307340@qq.com
* @Time:2016/8/1 1:35
* @version 1.0
* TODO
*/public class SearchFragment extends Fragment implements AdapterView.OnItemClickListener, View.OnClickListener {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
List<Recomend>data = null;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
RecomendAdapter adapter = null;
private OnFragmentInteractionListener mListener;
AutoClearEditText et_search;//我自定义的EditText
ImageButton ib_search;
ListView search_list;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SearchFragment.
*/
// TODO: Rename and change types and number of parameters
public static SearchFragment newInstance(String param1, String param2) {
SearchFragment fragment = new SearchFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search, container, false);
initView(view);
//暂时模拟填充数据
initData();
return view;
}
private void initView(View view) {
ib_search = (ImageButton) view.findViewById(R.id.search_button);
et_search = (AutoClearEditText) view.findViewById(R.id.search_edit);
search_list = (ListView) view.findViewById(R.id.search_list);
search_list.setTextFilterEnabled(true); // 开启过滤功能
ib_search.setOnClickListener(this);
//为EditText(搜素框)设置一个TextWatcher来监视输入的动作
et_search.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (TextUtils.isEmpty(charSequence.toString().trim()))
search_list.clearTextFilter();//搜索文本为空时,清除ListView的过滤
else
search_list.setFilterText(charSequence.toString().trim());//设置过滤关键字
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
private void initData(){
data = new ArrayList<>();
data.add(new Recomend("应用推荐","忙碌一天的你,怎么能没有一款好玩的游戏来放松一下呢"));
data.add(new Recomend("好书推荐","读过一本好书,像交了一个益友。——臧克家"));
data.add(new Recomend("养生推荐","三天不吃青,兩眼冒金星。寧可食無肉,不可飯無湯。吃面多喝湯,免得開藥方"));
data.add(new Recomend("资讯推荐","风声雨声读书声,声声入耳;家事国事天下事,事事关心,快来看看吧"));
data.add(new Recomend("更多推荐","吃喝玩乐学一应俱全,快来看看吧"));
data.add(new Recomend("更多推荐","吃喝玩乐学一应俱全,快来看看吧"));
data.add(new Recomend("更多推荐","吃喝玩乐学一应俱全,快来看看吧"));
data.add(new Recomend("更多推荐","吃喝玩乐学一应俱全,快来看看吧"));
adapter = new RecomendAdapter(getActivity(),data);
search_list.setAdapter(adapter);
search_list.setOnItemClickListener(this);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
ScreenUtils.showToast(data.get(i).getTitle());
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.search_button:
String search = et_search.getText().toString().trim();
if (TextUtils.isEmpty(search)){
search_list.clearTextFilter();//搜索文本为空时,过滤设置
}else {
// search_list.clearTextFilter();
search_list.setFilterText(search);//设置过滤关键字
}
break;
default:
break;
}
}
}
我在注释中已经注明了,需要注意的地方就是一定要先打开过滤功能 search_list.setTextFilterEnabled(true)
- 接下来是适配器的代码,关键代码;
/**
* @author 郑明亮 @email 1072307340@qq.com
* @version 1.0
* @time 2016/7/29 18:28
* TODO
*/
public class RecomendAdapter extends BaseAdapter implements Filterable{
Context context;
List<Recomend> data; //这个数据是会改变的,所以要有个变量来备份一下原始数据
List<Recomend> backData;//用来备份原始数据
MyFilter mFilter ;
public RecomendAdapter(Context context, List<Recomend> data) {
this.context = context;
this.data = data;
backData = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view ==null){
view = LayoutInflater.from(context).inflate(R.layout.fragment_recomend_item,null);
}
TextView tv_title = ViewHolder.get(view,R.id.tv_recomend_title);
TextView tv_desc = ViewHolder.get(view,R.id.tv_recomend_desc);
ImageView img = ViewHolder.get(view,R.id.iv_recomend_img);
tv_title.setText(data.get(i).getTitle());
tv_desc.setText(data.get(i).getDesc());
Glide.with(context).load(R.drawable.default_head_icon).asBitmap().centerCrop().placeholder(R.mipmap.ic_launcher).into(img);
return view;
}
//当ListView调用setTextFilter()方法的时候,便会调用该方法
@Override
public Filter getFilter() {
if (mFilter ==null){
mFilter = new MyFilter();
}
return mFilter;
}
//我们需要定义一个过滤器的类来定义过滤规则
class MyFilter extends Filter{
//我们在performFiltering(CharSequence charSequence)这个方法中定义过滤规则
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults result = new FilterResults();
List<Recomend> list ;
if (TextUtils.isEmpty(charSequence)){//当过滤的关键字为空的时候,我们则显示所有的数据
list = backData;
}else {//否则把符合条件的数据对象添加到集合中
list = new ArrayList<>();
for (Recomend recomend:backData){
if (recomend.getTitle().contains(charSequence)||recomend.getDesc().contains(charSequence)){
LogUtil.d("performFiltering:"+recomend.toString());
list.add(recomend);
}
}
}
result.values = list; //将得到的集合保存到FilterResults的value变量中
result.count = list.size();//将集合的大小保存到FilterResults的count变量中
return result;
}
//在publishResults方法中告诉适配器更新界面
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
data = (List<Recomend>)filterResults.values;
LogUtil.d("publishResults:"+filterResults.count);
if (filterResults.count>0){
notifyDataSetChanged();//通知数据发生了改变
LogUtil.d("publishResults:notifyDataSetChanged");
}else {
notifyDataSetInvalidated();//通知数据失效
LogUtil.d("publishResults:notifyDataSetInvalidated");
}
}
}
}
最后用search_list.setFilterText(search);//设置过滤关键字 会出现如效果图出现的黑色的框
可以使用adapter.getFilter().filter(s)就不会有那个框框了 。