如何在 BaseAdapter 中使用 getFilter() 过滤 ListView
Posted
技术标签:
【中文标题】如何在 BaseAdapter 中使用 getFilter() 过滤 ListView【英文标题】:How to filter ListView using getFilter() in BaseAdapter 【发布时间】:2012-09-09 12:11:25 【问题描述】:在我的应用程序中,我创建了一个自定义列表视图,我想实现一个过滤器,以便可以根据在 EditText 中输入的文本过滤列表。我将 BaseAdapter 用作单独的类,并在我的主活动中调用该类。我还在我的主要活动中实现了 addTextChangedListener(),我还在 BaseAdapter 类中实现了 getFilter()。但我不知道如何使用 getFilter() 并相应地过滤我的列表。在列表中,我添加来自 JSON URL 的值。请帮助我告诉我如何使用 getFilter() 来过滤我的列表。
Activity类的代码:
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView)findViewById(R.id.listView1);
et1 = (EditText)findViewById(R.id.editText1);
inflator = getLayoutInflater();
et1.addTextChangedListener(this);
JsonParser jParser = new JsonParser();
JSONObject json = jParser.getJSONfromUrl(url);
try
JSONArray explore = json.getJSONArray("explore");
for(int i=0; i<explore.length(); i++)
JSONObject exp = explore.getJSONObject(i);
list.add(exp.getString("username"));
catch(JSONException e)
e.printStackTrace();
srchadptr = new SearchAdapter(this, inflator, list);
lv.setAdapter(srchadptr);
public void afterTextChanged(Editable s)
// TODO Auto-generated method stub
srchadptr.getFilter().filter(s);
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
// TODO Auto-generated method stub
public void onTextChanged(CharSequence s, int start, int before, int count)
// TODO Auto-generated method stub
BaseAdapter类的代码:
public class SearchAdapter extends BaseAdapter implements Filterable
Context context;
LayoutInflater inflater;
Button btn;
View vw;
ArrayList<String> list = new ArrayList<String>();
public SearchAdapter(Context context, LayoutInflater inflater, ArrayList<String> list)
// TODO Auto-generated constructor stub
this.context = context;
this.inflater = inflater;
this.list = list;
/*public CharSequence filter(CharSequence cs)
return cs;
*/
public int getCount()
// TODO Auto-generated method stub
return list.size();
public Object getItem(int position)
// TODO Auto-generated method stub
return position;
public long getItemId(int position)
// TODO Auto-generated method stub
return position;
public View getView(final int position, View convertView, ViewGroup parent)
// TODO Auto-generated method stub
LinearLayout ll = (LinearLayout) vw;
final EditText edt = ((EditText)ll.getChildAt(0));
vw = inflater.inflate(R.layout.list_items, null);
ImageView img = (ImageView)vw.findViewById(R.id.imageView1);
TextView tv = (TextView)vw.findViewById(R.id.textView1);
btn = (Button)vw.findViewById(R.id.button1);
tv.setText(String.valueOf(list.get(position)));
btn.setText(String.valueOf(list.get(position)));
btn.setOnClickListener(new OnClickListener()
public void onClick(View v)
// TODO Auto-generated method stub
Toast.makeText(context, list.get(position), Toast.LENGTH_LONG).show();
);
return vw;
public android.widget.Filter getFilter()
// TODO Auto-generated method stub
return new android.widget.Filter()
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
// TODO Auto-generated method stub
@Override
protected FilterResults performFiltering(CharSequence constraint)
// TODO Auto-generated method stub
return null;
;
提前谢谢...
【问题讨论】:
***.com/questions/8678163/… 我已经查看了链接,但对我来说仍然没有用。还有一件事我的 getFlter() 不接受 @Override 它显示错误。所以请给我一个基本的解决方案。 很高兴知道一个工作示例对你没有用!!!! @Abhishek 如果你有 google 来解决 @Override 问题,你可能有很多解决方案。一个是将编译器从 1.5 更改为 1.6 ...从project-properties-java compiler
需要调用 notifyDataSetChanged() API
【参考方案1】:
我希望这个例子可以帮助你
在 Main_Activity 中
EditText etSearch;
BaseAdapterFilterable adapter;
etSearch.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
// Listview name of the class
Listview.this.adapter.getFilter().filter(s);
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
// TODO Auto-generated method stub
@Override
public void afterTextChanged(Editable s)
// TODO Auto-generated method stub
);
在你的适配器中把这个类用在getfilter方法中
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();
也在您的适配器中从 filter_here 类返回实例
@Override
public Filter getFilter()
// TODO Auto-generated method stub
return filter;
【讨论】:
最后一行是什么意思:“也在您的适配器中从 filter_here 类返回实例”?哪里需要添加这个返回过滤器? @ray 在您的适配器构造函数中从 filter_here 类“filter_here filter = new filter_here();”中初始化对象覆盖getfilter方法并返回过滤器 @OmarAbdan 你能帮忙吗:***.com/questions/20524417/… 在您的适配器中,只需将上面的方法放在 getView() 旁边.... ----------getView End--------- @Override public Filter getFilter () // TODO 自动生成的方法存根 return filter_here; --------------适配器类结束------------【参考方案2】:在您的 BaseAdapter 中,存储列表的两份副本,一份是原始的,一份是过滤的。并更改 BaseAdapter 中的所有引用,只使用过滤后的列表。
1) 在您的活动中,激活 ListView 上的过滤器: lv.setTextFilterEnabled(true);
2) 在您的 textWatcher 中,触发您的 listadapter 上的过滤器 srchadptr.getFilter().filter(s)
3) 更新您的 baseadapter 以存储数据的两个副本,并更改引用以引用过滤列表而不是原始列表。
public class SearchAdapter extends BaseAdapter implements Filterable
List<String> list = new ArrayList<String>();
List<String> listFiltered = new ArrayList<String>();
public SearchAdapter(Context context, ArrayList<String> list)
this.context = context;
this.inflater = LayoutInflater.from(context)
this.list = list;
this.listFiltered=list;
public int getCount()
return listFiltered.size();//note the change
public Object getItem(int position)
return listFiltered.get(position);//note the change
//only altered lines shown in this function (change ``list`` to ``listFiltered``)
public View getView(final int position, View convertView, ViewGroup parent)
tv.setText(String.valueOf(listFiltered.get(position)));
btn.setText(String.valueOf(listFiltered.get(position)));
btn.setOnClickListener(new OnClickListener()
public void onClick(View v)
Toast.makeText(context, listFiltered.get(position), Toast.LENGTH_LONG).show();
);
//now write your filter function
@Override
public Filter getFilter()
return new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0)
//no constraint given, just return all the data. (no search)
results.count = list.size();
results.values = list;
else //do the search
List<String> resultsData = new ArrayList<>();
String searchStr = constraint.toString().toUpperCase();
for (String s : list)
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)
listFiltered = (ArrayList<String>) results.values;
notifyDataSetChanged();
;
【讨论】:
【参考方案3】:我发现使用过滤器并不是那么方便。我是如何做到的:
((EditText)findViewById(R.id.etSearch)).addTextChangedListener(new TextWatcher()
private boolean mCountIncreased;
@Override
public void afterTextChanged(Editable s)
if (s.toString().length() == 0)
mDisplayedList.clear();
mDisplayedList.addAll(mFullList);
mListAdapter.notifyDataSetChanged();
return;
if (mCountIncreased)
mDisplayedList.clear();
mDisplayedList.addAll(mFullList);
List<Item> toRemove = new ArrayList<Item>();
for (Item item : mDisplayedList)
if (someCondition)
toRemove.add(currency);
mDisplayedList.removeAll(toRemove);
mListAdapter.notifyDataSetChanged();
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
mCountIncreased = after <= count;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
);
请注意,您必须更改适配器才能使用 mDisplayedList 而不是 mFullList.. 就是这样。
当您的列表包含大量条目时,这可能会产生一些开销。但我已经像这样处理 +-300 个项目的列表,但我没有注意到任何东西。
希望对你有帮助, 弗拉德
【讨论】:
以上是关于如何在 BaseAdapter 中使用 getFilter() 过滤 ListView的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 中获取 BaseAdapter 的上下文
如何在填充了 BaseAdapter 的 Fragment 中刷新 ListView?