2011-06-27 2 views
28

Jestem początkujący w systemie Android, ale starałem się zrobić niestandardowe filtrowanie listview i jakoś to zadziałało. Jedyny problem jaki mam to to, że ArrayList, że zachowałem wszystkie wartości ("original" ArrayList), jest coraz mniejszy na elementach w każdym filtrowaniu. Nie mogę tego wyjaśnić, ale myślałem, że możesz mi jakoś pomóc.ArrayAdapter niestandardowy Filter w ListView

Zresztą tu jest zwyczaj 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; 
} 

}

UWAGA: ListView jest poprawnie pokazując elementy, ale kiedy na exaple usunąć list, w polu edycji (która wyzwala filtrowanie) to tam zaczynają się problemy.

--- EDIT ---

@Janusz: Wielkie dzięki za odpowiedź. To rozwiązało mój problem.

Oto kod źródłowy, który pracuje dla mnie, więc jeśli ktoś ma ten sam problem mogli spróbować tego:

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

co jest dziełem 'clear()' i 'Add) (' funkcji. –

+0

@compileGuy, co to znaczy "Pkmn"? Nie mogę uruchomić tego przykładu. czy możesz przesłać kod całkowicie? –

+0

Doskonała implementacja @compileguy, dodawanie i usuwanie są funkcjami przez adapter, nie trzeba ich przekraczać. pkmn to klasa modelu przechowująca wartości danych na liście – Naruto

Odpowiedz

16

Twojego problemu są to linie:

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

sztuk jest lista, której używasz do swojego ListView i umieszczenie jej w dwóch różnych zmiennych, nie tworzy z niej dwóch różnych list. Podajesz tylko liście dwie różne nazwy.

Można użyć:

this.fitems = new ArrayList(items); 

które powinny generować nową listę i zmiany na tej liście zmieni tylko listę fitems.

+0

Dzięki Janusz, działa znakomicie dzięki partii – Naruto

+0

Nie działa dla mnie, Moja lista list znika, a po usunięciu całego ciągu nie przychodzi z powrotem. http://stackoverflow.com/questions/20524417/listview-is-blank-while-using-getfilter-function – Si8

+0

@ SiKni8 ja też otrzymuję ten sam wynik. proszę pomóż –

2

możesz osiągnąć ten sam efekt, tworząc po prostu metodę toString() w klasie Pkmn, która zwraca wartość, według której chcesz filtrować.

0

Najlepszym sposobem znalazłem się filtrować ArrayAdapter jest stworzyć własną klasę filtra:

private class MyFilter extends Filter 

następnie w tej funkcji utworzyć nową tablicę obiektów do wyświetlenia za filtrem (można znaleźć dobrego wykonania w Kod źródłowy class ArrayAdapter)

@Override 
protected FilterResults performFiltering(CharSequence prefix) 

teraz sztuką jest w tej metodzie

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

podczas korzystania z zasilacza Array ty nie to zrobić:

myAdapterData = results.values 

odtąd odłączeniu dane z Super danych, należy to zrobić, aby zachować swoje odniesienie do super oryginalnej tablicy danych:

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

i następnie zastąpić

getFilter() stanowi

w karty, na przykład:

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