使用自定义(对象)适配器过滤 ListView
Posted
技术标签:
【中文标题】使用自定义(对象)适配器过滤 ListView【英文标题】:Filtering ListView with custom (object) adapter 【发布时间】:2011-08-12 10:11:22 【问题描述】:我正在尝试对使用自定义对象适配器的 ListView 进行过滤,但我找不到任何有用的示例。包含的代码非常简化,所以请记住,我不能使用常规的 ArrayAdapter。 我在 ListView 上方有一个 EditText,当用户在 EditText 小部件中输入文本时,我想通过 EditText 中写入的文本过滤 ListView。 任何建议将不胜感激!
这是来自活动类的 sn-p:
public class management_objects extends Activity
private static List<User> UserList;
private EfficientAdapter adapter = null;
private ListView objectListView = null;
private EditText SearchText = null;
private static class EfficientAdapter extends BaseAdapter implements Filterable
private LayoutInflater mInflater;
public EfficientAdapter(Context context)
mInflater = LayoutInflater.from(context);
public int getCount()
return UserList.size();
public Object getItem(int position)
return position;
public long getItemId(int position)
return position;
public View getView(int position, View convertView, ViewGroup parent)
ViewHolder holder;
if (convertView == null)
convertView = mInflater.inflate(R.layout.imagelayout_2lines, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.managementObjectText);
holder.subtext = (TextView) convertView.findViewById(R.id.managementObjectSubText);
holder.icon = (ImageView) convertView.findViewById(R.id.managementObjectIcon);
convertView.setTag(holder);
else
holder = (ViewHolder) convertView.getTag();
holder.text.setText(UserList.get(position).getFirstName());
holder.subtext.setText(UserList.get(position).getLastName());
holder.icon.setImageResource(R.drawable.user);
return convertView;
static class ViewHolder
TextView text;
TextView subtext;
ImageView icon;
@Override
public Filter getFilter()
return null;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.adobjectlist);
Bundle extras = getIntent().getExtras();
SearchText = (EditText) findViewById(R.id.SearchBox);
SearchText.addTextChangedListener(filterTextWatcher);
objectListView = (ListView) findViewById(R.id.ObjectList);
objectListView.setOnItemClickListener(Item_Click);
adapter = new EfficientAdapter(this);
ComputerName = extras.getString("COMPUTER_NAME");
//Get User list from webservice
ShowUsers();
这是用户类:
public class User
private int UserId;
private String FirstName;
private String LastName;
public int getUserId()
return UserId;
public void setUserId(int UserId)
this.UserId = UserId;
public String getFirstName()
return FirstName;
public void setFirstName(String FirstName)
this.FirstName = FirstName;
public String getLastName()
return LastName;
public void setLastName(String LastName)
this.LastName = LastName;
【问题讨论】:
【参考方案1】:你需要做几件事:
1) 在您的活动中,在您的 EditText 上注册一个文本更改侦听器,其中包含用户输入的值:
mSearchValue.addTextChangedListener(searchTextWatcher);
2) 创建你的 searchTextWatcher 并让它做一些事情:
private TextWatcher searchTextWatcher = new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
// ignore
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
// ignore
@Override
public void afterTextChanged(Editable s)
Log.d(Constants.TAG, "*** Search value changed: " + s.toString());
adapter.getFilter().filter(s.toString());
;
3) 覆盖自定义适配器中的 getFilter() 并让它过滤结果并通知列表视图数据集已更改。
@Override
public Filter getFilter()
return new Filter()
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
Log.d(Constants.TAG, "**** PUBLISHING RESULTS for: " + constraint);
myData = (List<MyDataType>) results.values;
MyCustomAdapter.this.notifyDataSetChanged();
@Override
protected FilterResults performFiltering(CharSequence constraint)
Log.d(Constants.TAG, "**** PERFORM FILTERING for: " + constraint);
List<MyDataType> filteredResults = getFilteredResults(constraint);
FilterResults results = new FilterResults();
results.values = filteredResults;
return results;
;
【讨论】:
为什么在 3) 中说“覆盖”? BaseAdapter 没有 getFilter()。 很好——不需要。我的自定义适配器类(实际上是从 AmazingListView 开源小部件的 AmazingAdapter 继承)实现需要 getFilter() 的 android.widget.Filterable 接口。 This tutorial 帮助了我。答案有一些不清楚的地方,或者我没有足够专注地阅读它。 @Dustin 这个 getFilteredResults(constraint) 方法是什么?我试过你的答案。但该方法不支持ne。 @anuruddhika,这只是您进行所需过滤的方法,并将返回结果。这不是您要覆盖的 Android 方法。【参考方案2】:这是一个有趣的例子
public Filter getFilter()
return new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
final FilterResults oReturn = new FilterResults();
final ArrayList<station> results = new ArrayList<station>();
if (orig == null)
orig = items;
if (constraint != null)
if (orig != null && orig.size() > 0)
for (final station g : orig)
if (g.getName().toLowerCase()
.contains(constraint.toString()))
results.add(g);
oReturn.values = results;
return oReturn;
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results)
items = (ArrayList<station>) results.values;
notifyDataSetChanged();
;
public void notifyDataSetChanged()
super.notifyDataSetChanged();
notifyChanged = true;
【讨论】:
使用 ORIG 变量保存初始实例的绝佳方法。效果很好,谢谢。【参考方案3】:对于那些不需要Filterable
接口的人来说,有一个更简单的解决方案。这也可以在其他解决方案失败的情况下正确处理notifyDataSetChanged()
。请注意,您需要在 BaseAdapter
中添加一个 getArray()
函数,该函数只返回传递给构造函数的数组对象。
public abstract class BaseFilterAdapter<T> extends BaseAdapter<T>
private List<T> original;
private String lastFilter;
public BaseFilterAdapter(Context context, List<T> array)
super(context, new LinkedList<T>());
original = array;
filter("");
protected abstract Boolean predicate(T element, String filter);
public void filter(String filter)
lastFilter = filter;
super.getArray().clear();
for (T element : original)
if (predicate(element, filter))
super.getArray().add(element);
super.notifyDataSetChanged();
@Override
public List<T> getArray()
return original;
@Override
public void notifyDataSetChanged()
filter(lastFilter);
【讨论】:
BaseAdapter 类中没有可覆盖的 getArray 方法。【参考方案4】:在您的基类上添加 toString 覆盖。例如
@Override
public String toString()
return this.name;
Above 使您的 List 成为字符串列表。所以你可以使用:
your_edit_text.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
YourActivity.this.YourAdapter.getFilter().filter(arg0);
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
@Override
public void afterTextChanged(Editable arg0)
);
【讨论】:
以上是关于使用自定义(对象)适配器过滤 ListView的主要内容,如果未能解决你的问题,请参考以下文章
带有过滤器 Android 的自定义 Listview 适配器