作者:zml_2015
原文:https://blog.csdn.net/zml_2015/article/details/52082174
實現(xiàn)ListView過濾功能最方便的便是使用ArrayAdapter亲配,里面自帶的getFilter()方法能很方便的實現(xiàn)此功能
但是在實際的開發(fā)中,ArrayAdapter有的時候滿足不了我們項目的各種需求罕偎,所以一般都是繼承于BaseAdapter吱抚,然后繼承BaseAdapter不能像ArrayAdapter那樣直接通過ListView的setTextFilter()就對ListView進行簡單的過濾朱巨,我們需要去手動實現(xiàn)一個Filterable接口糕再,自定義過濾規(guī)則撒顿;
效果圖
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);
//暫時模擬填充數(shù)據(jù)
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(搜素框)設(shè)置一個TextWatcher來監(jiān)視輸入的動作
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());//設(shè)置過濾關(guān)鍵字
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
private void initData(){
data = new ArrayList<>();
data.add(new Recomend("應(yīng)用推薦","忙碌一天的你离熏,怎么能沒有一款好玩的游戲來放松一下呢"));
data.add(new Recomend("好書推薦","讀過一本好書佳谦,像交了一個益友∽檀粒——臧克家"));
data.add(new Recomend("養(yǎng)生推薦","三天不吃青钻蔑,兩眼冒金星啥刻。寧可食無肉,不可飯無湯矢棚。吃面多喝湯郑什,免得開藥方"));
data.add(new Recomend("資訊推薦","風(fēng)聲雨聲讀書聲,聲聲入耳蒲肋;家事國事天下事蘑拯,事事關(guān)心,快來看看吧"));
data.add(new Recomend("更多推薦","吃喝玩樂學(xué)一應(yīng)俱全兜粘,快來看看吧"));
data.add(new Recomend("更多推薦","吃喝玩樂學(xué)一應(yīng)俱全申窘,快來看看吧"));
data.add(new Recomend("更多推薦","吃喝玩樂學(xué)一應(yīng)俱全,快來看看吧"));
data.add(new Recomend("更多推薦","吃喝玩樂學(xué)一應(yīng)俱全孔轴,快來看看吧"));
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();//搜索文本為空時剃法,過濾設(shè)置
}else {
// search_list.clearTextFilter();
search_list.setFilterText(search);//設(shè)置過濾關(guān)鍵字
}
break;
default:
break;
}
}
}
我在注釋中已經(jīng)注明了,需要注意的地方就是一定要先打開過濾功能 search_list.setTextFilterEnabled(true)
- 接下來是適配器的代碼路鹰,關(guān)鍵代碼贷洲;
/**
* @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; //這個數(shù)據(jù)是會改變的,所以要有個變量來備份一下原始數(shù)據(jù)
List<Recomend> backData;//用來備份原始數(shù)據(jù)
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;
}
//當(dāng)ListView調(diào)用setTextFilter()方法的時候晋柱,便會調(diào)用該方法
@Override
public Filter getFilter() {
if (mFilter ==null){
mFilter = new MyFilter();
}
return mFilter;
}
//我們需要定義一個過濾器的類來定義過濾規(guī)則
class MyFilter extends Filter{
//我們在performFiltering(CharSequence charSequence)這個方法中定義過濾規(guī)則
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults result = new FilterResults();
List<Recomend> list ;
if (TextUtils.isEmpty(charSequence)){//當(dāng)過濾的關(guān)鍵字為空的時候优构,我們則顯示所有的數(shù)據(jù)
list = backData;
}else {//否則把符合條件的數(shù)據(jù)對象添加到集合中
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();//通知數(shù)據(jù)發(fā)生了改變
LogUtil.d("publishResults:notifyDataSetChanged");
}else {
notifyDataSetInvalidated();//通知數(shù)據(jù)失效
LogUtil.d("publishResults:notifyDataSetInvalidated");
}
}
}
}
最后用search_list.setFilterText(search);//設(shè)置過濾關(guān)鍵字 會出現(xiàn)如效果圖出現(xiàn)的黑色的框
可以使用adapter.getFilter().filter(s)就不會有那個框框了 。