2011-06-27 19 views
28

Soy un principiante en Android, pero traté de hacer un filtro de vista de lista personalizado y funcionó de alguna manera. El único problema que tengo es que ArrayList que conservé todos los valores (ArrayList "original") es cada vez más bajo en los elementos en cada filtrado. No puedo explicar esto, pero pensé que podías ayudarme de alguna manera.Filtrado personalizado ArrayAdapter en ListView

De todos modos aquí es el ArrayAdaptor personalizado:

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

}

NOTA: La vista de lista muestra correctamente los artículos, pero cuando por exaple elimino una letra en el cuadro de edición (que activa el filtrado) este es donde comienzan los problemas

--- --- EDITAR

@Janusz: Muchas gracias por su respuesta. Eso resolvió mi problema.

Aquí está el código fuente que funciona para mí, así que si alguien tiene el mismo problema que podría probar esto:

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

lo que es el trabajo de la función 'clear()' y 'add()'. –

+0

@compileGuy, ¿qué significa "Pkmn"? No puedo ejecutar este ejemplo. ¿podrías subir el código por completo? –

+0

Excelente implementación @compileguy, agregar y borrar son funcionalidades por adaptador, no necesita sobreponerlas. pkmn es una clase modelo para contener los valores de los datos en la lista – Naruto

Respuesta

16

Su problema son estas líneas:

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

piezas, constituye el La lista que utiliza para su ListView y ponerlo en dos variables diferentes no hace dos listas diferentes. Solo le está dando a la lista elementos de dos nombres diferentes.

Se puede utilizar:

this.fitems = new ArrayList(items); 

que debe generar una nueva lista y cambios en esta lista sólo cambiará la lista fitems.

+0

Gracias Janusz, funciona genial Gracias lote – Naruto

+0

No funciona para mí, Mi ListView desaparece y cuando elimino la cadena completa no aparece de nuevo. http://stackoverflow.com/questions/20524417/listview-is-blank-while-using-getfilter-function – Si8

+0

@ SiKni8 yo también obtengo el mismo resultado. por favor ayuda –

2

puede lograr el mismo efecto simplemente creando un método toString() en su clase Pkmn que devuelve el valor que desea filtrar.

0

La mejor manera que encontré para filtrar ArrayAdapter es crear mi propia clase de filtro:

private class MyFilter extends Filter 

entonces en esa función de crear la nueva tabla de objeto a mostrar después del filtro (se puede encontrar una buena aplicación en el código fuente de class ArrayAdapter)

@Override 
protected FilterResults performFiltering(CharSequence prefix) 

ahora el truco está en este método

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

cuando se utiliza el adaptador de matriz que no puede hacer esto:

myAdapterData = results.values 

desde entonces se desconecta sus datos a partir de los datos de súper, usted debe hacer esto para mantener su referencia a la matriz de datos super original:

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

y luego anular

getFilter()

en su adaptador, por ejemplo:

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