如何在 BaseAdapter 上实现 getFilter?
Posted
技术标签:
【中文标题】如何在 BaseAdapter 上实现 getFilter?【英文标题】:How to implement getFilter on a BaseAdapter? 【发布时间】:2012-07-22 02:56:05 【问题描述】:我正在尝试在基本适配器上实现 getFilter() 以过滤掉列表上的搜索结果。有没有如何实现 getFilter() 的示例?
MainActivity.java
final AppInfoAdapter adapter = new AppInfoAdapter(this, Utilities.getSystemFilteredApplication(this), getPackageManager());
public void onTextChanged(CharSequence s, int start, int before,
int count)
adapter.getFilter().filter(s); //Filter from my adapter
adapter.notifyDataSetChanged(); //Update my view
AppInfoAdapter.java
package com.example.permission;
import java.util.List;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
public class AppInfoAdapter extends BaseAdapter implements Filterable
private Context mContext;
private List mListAppInfo;
PackageManager mPackManager;
public AppInfoAdapter(Context c, List list, PackageManager pm)
mContext = c;
mListAppInfo = list;
mPackManager = pm;
public int getCount()
return mListAppInfo.size();
public Object getItem(int position)
return mListAppInfo.get(position);
public long getItemId(int position)
return position;
public View getView(int position, View convertView, ViewGroup parent)
// get the selected entry
ApplicationInfo entry = (ApplicationInfo) mListAppInfo.get(position);
// reference to convertView
View v = convertView;
// inflate new layout if null
if(v == null)
LayoutInflater inflater = LayoutInflater.from(mContext);
v = inflater.inflate(R.layout.layout_appinfo, null);
// load controls from layout resources
ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);
// set data to display
ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
tvAppName.setText(entry.loadLabel(mPackManager));
tvPkgName.setText(entry.packageName);
// return view
return v;
public Filter getFilter()
// TODO Auto-generated method stub
return null;
编辑:编辑代码并添加完整的 AppInfoAdapter.java
【问题讨论】:
【参考方案1】:在你的适配器中放入这个类以在 getfilter 方法中使用它
//this is a simple class that filtering the ArrayList of strings used in adapter
public class filter_here extends Filter
@Override
protected FilterResults performFiltering(CharSequence constraint)
// TODO Auto-generated method stub
FilterResults Result = new FilterResults();
// if constraint is empty return the original names
if(constraint.length() == 0 )
Result.values = Original_Names;
Result.count = Original_Names.size();
return Result;
ArrayList<String> Filtered_Names = new ArrayList<String>();
String filterString = constraint.toString().toLowerCase();
String filterableString;
for(int i = 0; i<Original_Names.size(); i++)
filterableString = Original_Names.get(i);
if(filterableString.toLowerCase().contains(filterString))
Filtered_Names.add(filterableString);
Result.values = Filtered_Names;
Result.count = Filtered_Names.size();
return Result;
@Override
protected void publishResults(CharSequence constraint,FilterResults results)
// TODO Auto-generated method stub
Names = (ArrayList<String>) results.values;
notifyDataSetChanged();
在 getfilter 中从中返回实例
@Override
public Filter getFilter()
// TODO Auto-generated method stub
return filter;
full example
【讨论】:
【参考方案2】:这差点让我死了:)
-
像这样实现您的 BaseAdapter:
在您的公共适配器类中定义一个 List 的 ArrayList,它将包含原始列表的临时项目。
public class MyAdapter extends BaseAdapter implements Filterable
public static ArrayList<String> temporarylist;
public static ArrayList<String> OriginalList;
private Activity activity;
public MyAdapter(Activity activity, ArrayList<String> OriginalList)
super();
this.activity=activity;
this.OriginalList = OriginalList;
temporarylist=OriginalList;
.
.
.
用以下代码创建getFilter()方法[作为例子]:
public Filter getFilter()
Filter filter = new Filter()
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
temporarylist=(ArrayList<String>)results.values;
notifyDataSetChanged();
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults results = new FilterResults();
ArrayList<String> FilteredList= new ArrayList<String>();
if (constraint == null || constraint.length() == 0)
// No filter implemented we return all the list
results.values = OriginalList;
results.count = OriginalList.size();
else
for (int i = 0; i < OriginalList.size(); i++)
String data = OriginalList.get(i);
if (data.toLowerCase().contains(constraint.toString()))
FilteredList.add(data);
results.values = FilteredList;
results.count = FilteredList.size();
return results;
;
return filter;
最后在您的 EditText 活动中:
MyAdapter adapter;
ArrayList<String> items;
ListView list = (ListView) findViewById(R.id.list);
items = new ArrayList<String>();
for (int i=0;i<30;i++)
items.add("Hello world "+String.valueof(i));
adapter = new GameAdapter(this, items);
list.setAdapter(adapter);
EditText inputSearch = (EditText) findViewById(R.id.Search_txt);
inputSearch.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3)
// When user changed the Text
MyActivity.this.adapter.getFilter().filter(cs);
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3)
// TODO Auto-generated method stub
@Override
public void afterTextChanged(Editable arg0)
// TODO Auto-generated method stub
);
【讨论】:
【参考方案3】:你能发布你的完整AppInfoAdapter
吗?还有任何理由从BaseAdapter
延伸而不是ArrayAdapter
?如果你有ArrayList
的对象,使用ArrayAdapter
,它已经实现了Filterable
接口。
实际上您使用的是List
,您的适配器可以重写为扩展ArrayAdapter
,它已经是Filterable
。
public class AppInfoAdapter extends ArrayAdapter<ApplicationInfo>
private Context mContext;
PackageManager mPackManager;
public AppInfoAdapter(Context c, List<ApplicationInfo> list, PackageManager pm)
super(c, 0, new ArrayList<ApplicationInfo>());
mContext = c;
mPackManager = pm;
@Override
public View getView(int position, View convertView, ViewGroup parent)
// get the selected entry
ApplicationInfo entry = (ApplicationInfo) getItem(position);
// reference to convertView
View v = convertView;
// inflate new layout if null
if(v == null)
LayoutInflater inflater = LayoutInflater.from(mContext);
v = inflater.inflate(R.layout.layout_appinfo, null);
// load controls from layout resources
ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);
// set data to display
ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
tvAppName.setText(entry.loadLabel(mPackManager));
tvPkgName.setText(entry.packageName);
// return view
return v;
【讨论】:
我编辑了答案,所以你的适配器extends Filterable ArrayAdapter
。
您的代码没有错误,但现在我看不到已安装应用程序的列表,只有 EditText
把super(c, 0, new ArrayList<ApplicationInfo>());
换成super(c, 0, list);
是我的错。
搜索部分工作,无法真正理解它是如何工作的,现在它有点错误,到目前为止它只适用于关键字'android'
查看ArrayAdapter
来源以了解ArrayFilter
的工作原理github.com/android/platform_frameworks_base/blob/master/core/… 或者这也可能有助于***.com/a/4027085/1300995【参考方案4】:
您需要返回一个Filter
的实例。要编写过滤器,请继承 Filter
并实现 performFiltering
和 publishResults
。请参阅docs。
【讨论】:
【参考方案5】:一般程序
-
在您的 ListView 上启用文本过滤
更改您的 baseadapter 以存储列表的 两份 副本,一份原件,一份过滤。
将 BaseAdapter 中的所有访问引用更改为引用过滤列表,而不是原始列表。
在 BaseAdapter 中实现您的过滤器功能。
第 1 步:listview.setTextFilterEnabled(true);
第二步:
public class AppInfoAdapter extends BaseAdapter implements Filterable
private List mListAppInfo;
private List mListAppInfoFiltered;
public AppInfoAdapter(Context c, List list, PackageManager pm)
mContext = c;
mListAppInfo = list;
mPackManager = pm;
mPackManagerFiltered = pm; //added line
第三步:
public int getCount()
return mListAppInfoFiltered.size();
public Object getItem(int position)
return mListAppInfoFiltered.get(position);
public View getView(int position, View convertView, ViewGroup parent)
// get the selected entry
ApplicationInfo entry = (ApplicationInfo) mListAppInfoFiltered.get(position);
第 4 步: 我不确定你的列表是什么类型,所以假设一个字符串列表:
@Override
public Filter getFilter()
return new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0)
//no search, so just return all the data
results.count = mListAppInfo.size();
results.values = mListAppInfo;
else //do the search
List<String> resultsData = new ArrayList<>();
String searchStr = constraint.toString().toUpperCase();
for (String s : mListAppInfo)
if (s.toUpperCase().contains(searchStr)) resultsData.add(s);
results.count = resultsData.size();
results.values = resultsData;
return results;
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
mListAppInfoFiltered = (ArrayList<MyObject>) results.values;
notifyDataSetChanged();
;
【讨论】:
【参考方案6】:getFilter() 可以在适配器中被覆盖并返回包含过滤列表的过滤器对象。 Filter() 类中有两个关键方法; performFiltering 和 publishResults。第一种方法在工作线程中执行过滤,后一种方法返回过滤后的对象列表。
您可以参考下面的示例代码
@Override
public Filter getFilter()
return new Filter()
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
// TODO Auto-generated method stub
if (results.count == 0)
notifyDataSetInvalidated();
else
mListAppInfo = (ArrayList<SampleItem>) results.values;
notifyDataSetChanged();
@Override
protected FilterResults performFiltering(CharSequence constraint)
// TODO Auto-generated method stub
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0)
results.values = mListAppInfo;
results.count = mListAppInfo.size();
else
ArrayList<SampleItem> filter_items = new ArrayList<>();
for (SampleItem item : mListAppInfo)
if (item.getItemName().toLowerCase().startsWith(constraint.toString().toLowerCase()))
filter_items.add(item);
results.values = filter_items ;
results.count = filter_items.size();
return results;
;
希望你觉得它有用。
【讨论】:
【参考方案7】:使用 ArrayAdapter 扩展您的类,然后覆盖方法,并创建过滤器类的对象并返回。
【讨论】:
以上是关于如何在 BaseAdapter 上实现 getFilter?的主要内容,如果未能解决你的问题,请参考以下文章