使用自定义(对象)适配器筛选ListView
我试图实现过滤使用自定义对象适配器的ListView,但我找不到任何有用的示例。 包含的代码是非常简单的,所以不要记住我不能使用常规的ArrayAdapter。 我在ListView上面有一个EditText,并且当用户在EditText小部件中input文本时,我想通过EditText中写入的文本过滤ListView。 我们欢迎所有的build议!
以下是活动类的片段:
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)在您的活动中,在您的EditText上注册包含用户input的值的文本更改侦听器:
mSearchValue.addTextChangedListener(searchTextWatcher);
2)创build你的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; } }; }
这里有个有趣的例子
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; }
对于那些不需要Filterable
接口的人来说,有一个更简单的解决scheme。 在其他解决scheme失败的情况下,这也正确处理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); } }
在您的基类上添加toString重写。 例如
@Override public String toString() { return this.name; }
以上使您的列表作为string列表。 所以你可以使用:
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) { } });