2011-06-27 6 views
28

Je suis un begginer dans Android mais j'ai essayé de faire un filtrage de listview personnalisé et j'ai travaillé d'une manière ou d'une autre. Le seul problème que j'ai est que le ArrayList que j'ai gardé toutes les valeurs ("original" ArrayList), devient de plus en plus bas sur les éléments dans chaque filtrage. Je ne peux pas expliquer cela mais j'ai pensé que vous pouvez m'aider d'une manière ou d'une autre.Filtrage personnalisé ArrayAdapter dans ListView

Quoi qu'il en soit ici est la coutume ArrayAdaptor:

public class PkmnAdapter extends ArrayAdapter<Pkmn> { 

private ArrayList<Pkmn> original; 
private ArrayList<Pkmn> fitems; 
private Filter filter; 

public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { 
     super(context, textViewResourceId, items); 
     this.original = items;//new ArrayList<Pkmn>(); 
     this.fitems = items;//new ArrayList<Pkmn>(); 
} 

@Override 
public void add(Pkmn item){ 
    original.add(item); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.row, null); 
     } 
     Pkmn pkmn = original.get(position); 
     if (pkmn != null) { 
       TextView tt = (TextView) v.findViewById(R.id.RlabPName); 
       TextView dex = (TextView)v.findViewById(R.id.RlabDex); 
       ImageView img = (ImageView)v.findViewById(R.id.RimgPkmn); 

       if (tt != null) { tt.setText(pkmn.getName()); } 
       if (dex != null){ dex.setText(CalcDex(pkmn.getId())); } 
       if (img != null){ 
        int resId = getContext().getResources().getIdentifier("dex" + pkmn.getId(), "drawable", "com.compileguy.pokebwteam"); 
        img.setImageResource(resId); 
       } 
     } 
     return v; 
} 

@Override 
public Filter getFilter() 
{ 
    if (filter == null) 
     filter = new PkmnNameFilter(); 

    return filter; 
} 

private class PkmnNameFilter extends Filter 
{ 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      FilterResults results = new FilterResults(); 
      String prefix = constraint.toString().toLowerCase(); 

      if (prefix == null || prefix.length() == 0) 
      { 
       ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); 
       results.values = list; 
       results.count = list.size(); 
      } 
      else 
      { 
       final ArrayList<Pkmn> list = original; 

       int count = list.size(); 
       final ArrayList<Pkmn> nlist = new ArrayList<Pkmn>(count); 

       for (int i=0; i<count; i++) 
       { 
        final Pkmn pkmn = list.get(i); 
        final String value = pkmn.getName().toLowerCase(); 

        if (value.startsWith(prefix)) 
        { 
         nlist.add(pkmn); 
        } 
       } 
       results.values = nlist; 
       results.count = nlist.size(); 
      } 
      return results; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      fitems = (ArrayList<Pkmn>)results.values; 
      clear(); 
      int count = fitems.size(); 
      for (int i=0; i<count; i++) 
      { 
       Pkmn pkmn = (Pkmn)fitems.get(i); 
       add(pkmn); 
      } 

      if (fitems.size() > 0) 
       notifyDataSetChanged(); 
      else 
       notifyDataSetInvalidated(); 
     } 

    } 


private String CalcDex(int id){ 
    String s = String.valueOf(id); 
    if (s.length() == 1) 
     s = "00"+s; 
    else if (s.length() == 2) 
     s = "0"+s; 
    return '#'+s; 
} 

}

NOTE: Le listview montre correctement les articles mais quand pour exaple supprimer une lettre dans la boîte de texte (qui déclenche le filtrage), ce est où les problèmes commencent.

--- EDIT ---

@Janusz: Merci beaucoup pour votre réponse. Cela a résolu mon problème.

Voici le code source qui fonctionne pour moi, donc si quelqu'un a le même problème, ils pourraient essayer celui-ci:

private ArrayList<Pkmn> original; 
private ArrayList<Pkmn> fitems; 
private Filter filter; 

public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { 
     super(context, textViewResourceId, items); 
     this.original = new ArrayList<Pkmn>(items); 
     this.fitems = new ArrayList<Pkmn>(items); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.row, null); 
     } 
     Pkmn pkmn = fitems.get(position); 
     if (pkmn != null) { 
       TextView tt = (TextView) v.findViewById(R.id.RlabPName); 
       TextView dex = (TextView)v.findViewById(R.id.RlabDex); 
       ImageView img = (ImageView)v.findViewById(R.id.RimgPkmn); 

       if (tt != null) { tt.setText(pkmn.getName()); } 
       if (dex != null){ dex.setText(CalcDex(pkmn.getId())); } 
       if (img != null){ 
        int resId = getContext().getResources().getIdentifier("dex" + pkmn.getId(), "drawable", "com.compileguy.pokebwteam"); 
        img.setImageResource(resId); 
       } 
     } 
     return v; 
} 

@Override 
public Filter getFilter() 
{ 
    if (filter == null) 
     filter = new PkmnNameFilter(); 

    return filter; 
} 

private class PkmnNameFilter extends Filter 
{ 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      FilterResults results = new FilterResults(); 
      String prefix = constraint.toString().toLowerCase(); 

      if (prefix == null || prefix.length() == 0) 
      { 
       ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); 
       results.values = list; 
       results.count = list.size(); 
      } 
      else 
      { 
       final ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); 
       final ArrayList<Pkmn> nlist = new ArrayList<Pkmn>(); 
       int count = list.size(); 

       for (int i=0; i<count; i++) 
       { 
        final Pkmn pkmn = list.get(i); 
        final String value = pkmn.getName().toLowerCase(); 

        if (value.startsWith(prefix)) 
        { 
         nlist.add(pkmn); 
        } 
       } 
       results.values = nlist; 
       results.count = nlist.size(); 
      } 
      return results; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      fitems = (ArrayList<Pkmn>)results.values; 

      clear(); 
      int count = fitems.size(); 
      for (int i=0; i<count; i++) 
      { 
       Pkmn pkmn = (Pkmn)fitems.get(i); 
       add(pkmn); 
      } 
     } 

    } 
} 
+0

ce qui est le travail de la fonction 'clear()' et 'ajouter()'. –

+0

@compileGuy, que signifie "Pkmn"? Je ne peux pas exécuter cet exemple. pourriez-vous télécharger du code complètement? –

+0

Excellente implémentation @compileguy, ajouter et effacer sont des fonctionnalités par adaptateur, vous n'avez pas besoin de les contourner. pkmn est une classe de modèle pour contenir les valeurs de données dans la liste – Naruto

Répondre

16

Votre problème sont ces lignes:

this.original = items; 
this.fitems = items; 

articles est la liste que vous utilisez pour votre ListView et le mettre dans deux variables différentes n'en fait pas deux listes différentes. Vous ne donnez que deux noms différents aux éléments de la liste.

Vous pouvez utiliser:

this.fitems = new ArrayList(items); 

qui devrait générer une nouvelle liste et les changements sur cette liste ne fera que changer la liste des fitems.

+0

Merci Janusz, ça marche génial merci beaucoup – Naruto

+0

Ne fonctionne pas pour moi, Ma ListView disparaît et quand je supprime la chaîne entière il ne vient pas de retour. http://stackoverflow.com/questions/20524417/listview-is-blank-while-using-getfilter-function – Si8

+0

@ SiKni8 moi aussi obtenir le même résultat. s'il vous plaît aide –

2

Vous pouvez obtenir le même effet en créant simplement une méthode toString() sur votre classe Pkmn qui renvoie la valeur que vous souhaitez filtrer.

0

La meilleure façon que je trouve à filtrer ArrayAdapter est de créer ma propre classe de filtre:

private class MyFilter extends Filter 

puis dans cette fonction créer le nouveau tableau d'objets pour afficher après le filtre (vous pouvez trouver la bonne mise en œuvre dans le code source de class ArrayAdapter)

@Override 
protected FilterResults performFiltering(CharSequence prefix) 

maintenant l'astuce est dans cette méthode

@Override 
protected void publishResults(CharSequence constraint, FilterResults results) 

lorsque vous utilisez l'adaptateur Array vous ne pouvez pas faire:

myAdapterData = results.values 

depuis lors, vous débranchez vos données à partir des données de super, vous devez le faire pour garder votre référence au super tableau de données d'origine:

data.clear(); 
data.addAll((List<YourType>) results.values); 

puis remplacer

getFilter()

dans votre adaptateur, par exemple:

@Override 
public Filter getFilter() { 
    if (filter == null) { 
     filter = new MyFilter(); 
    } 
    return filter; 
} 
Questions connexes