Filtrage de ListView avec un adaptateur personnalisé (object)

J’essaie d’implémenter le filtrage d’un ListView qui utilise un adaptateur d’object personnalisé, mais je ne trouve aucun échantillon utile. Le code inclus est très simplifié, alors n’oubliez pas que je ne peux pas utiliser un ArrayAdapter standard. J’ai un EditText au-dessus de ListView, et lorsque l’utilisateur entre du texte dans le widget EditText, je voudrais filtrer la ListView par le texte écrit dans EditText. Toutes les suggestions seraient très appréciées!

Voici l’extrait de la classe d’activité:

public class management_objects extends Activity { private static List 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.getSsortingng("COMPUTER_NAME"); //Get User list from webservice ShowUsers(); } 

Voici la classe User:

  public class User { private int UserId; private Ssortingng FirstName; private Ssortingng LastName; public int getUserId() { return UserId; } public void setUserId(int UserId) { this.UserId = UserId; } public Ssortingng getFirstName() { return FirstName; } public void setFirstName(Ssortingng FirstName) { this.FirstName = FirstName; } public Ssortingng getLastName() { return LastName; } public void setLastName(Ssortingng LastName) { this.LastName = LastName; } } 

Vous devez faire quelques choses:

1) Dans votre activité, inscrivez-vous pour un écouteur de changement de texte sur votre EditText qui contient la valeur saisie par l’utilisateur:

mSearchValue.addTextChangedListener (searchTextWatcher);

2) Créez votre searchTextWatcher et faites-le faire:

 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.toSsortingng()); adapter.getFilter().filter(s.toSsortingng()); } }; 

3) Remplacez getFilter () dans votre adaptateur personnalisé et faites-le filtrer les résultats et notifiez la vue de liste que le jeu de données a changé.

  @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) results.values; MyCustomAdapter.this.notifyDataSetChanged(); } @Override protected FilterResults performFiltering(CharSequence constraint) { Log.d(Constants.TAG, "**** PERFORM FILTERING for: " + constraint); List filteredResults = getFilteredResults(constraint); FilterResults results = new FilterResults(); results.values = filteredResults; return results; } }; } 

Voici un exemple intéressant

 public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { final FilterResults oReturn = new FilterResults(); final ArrayList results = new ArrayList(); 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.toSsortingng())) results.add(g); } } oReturn.values = results; } return oReturn; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { items = (ArrayList) results.values; notifyDataSetChanged(); } }; } public void notifyDataSetChanged() { super.notifyDataSetChanged(); notifyChanged = true; } 

Pour ceux qui n’ont pas besoin de l’interface Filterable , la solution est beaucoup plus simple. Cela gère également notifyDataSetChanged() correctement lorsque les autres solutions échouent. Notez que vous devez append une fonction getArray() au BaseAdapter qui renvoie uniquement l’object tableau qui a été transmis au constructeur.

 public abstract class BaseFilterAdapter extends BaseAdapter { private List original; private Ssortingng lastFilter; public BaseFilterAdapter(Context context, List array) { super(context, new LinkedList()); original = array; filter(""); } protected abstract Boolean predicate(T element, Ssortingng filter); public void filter(Ssortingng filter) { lastFilter = filter; super.getArray().clear(); for (T element : original) if (predicate(element, filter)) super.getArray().add(element); super.notifyDataSetChanged(); } @Override public List getArray() { return original; } @Override public void notifyDataSetChanged() { filter(lastFilter); } } 

Ajoutez toSsortingng à votre classe de base. Par exemple

 @Override public Ssortingng toSsortingng() { return this.name; } 

Ci-dessus rend votre liste comme liste de chaînes. Donc, vous pouvez utiliser:

 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) { } });