Filtering ListView with custom (object) adapter
我正在尝试实现使用自定义对象适配器的ListView的筛选,但找不到任何有用的示例。所包含的代码非常简单,因此请记住,我不能使用常规的arrayadapter。我在ListView上面有一个EditText,当用户在EditText小部件中输入文本时,我希望通过EditText中写入的文本来过滤ListView。任何建议都将不胜感激!
下面是Activity类中的代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 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(); } |
这是用户类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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上注册文本更改侦听器:
mSearchValue.addTextChangedListener(searchTextWatcher);
2)创建SearchTextWatcher并让它执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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(),让它过滤结果,并通知ListView数据集已更改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @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; } }; } |
这里有一个有趣的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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; } |
对于那些不需要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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重写。例如
1 2 3 4 | @Override public String toString() { return this.name; } |
上面将您的列表作为字符串列表。所以你可以使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) { } }); |