Filtrado personalizado ArrayAdapter en ListView
Soy un begginer en Android, pero he intentado hacer un filtro de listview personalizado y yo funcionó de alguna manera. El único problema que tengo es que el ArrayList que guardé todos los valores ("original" ArrayList), está consiguiendo más bajo y más bajo en artículos en cada filtrado. No puedo explicar esto pero pensé que puedes ayudarme de alguna manera.
De todos modos aquí es el Custom ArrayAdaptor:
- Filtro ListView con arrayadapter
- Vista de búsqueda de Android en los datos de Firebase
- Cómo restablecer listview después de searchview se cierra en android?
- IllegalStateException: El contenido del adaptador ha cambiado pero ListView no recibió una notificación
- ¿En qué componentes de interfaz de usuario deben utilizarse los filtros y / o la clasificación?
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: El listview muestra correctamente los elementos pero cuando para exaple elimino una letra en el editbox (que desencadena el filtrado) aquí es donde empiezan 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 intentar este:
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); } } } }
- Filtrado personalizado en Android con ArrayAdapter
- ¿Cómo excluir ciertos mensajes por el nombre de TAG utilizando Android adb logcat?
- Filtro ListView con CursorLoader Y FilterQueryProvider?
- ¿Cómo anular el filtro en el ArrayAdapter de Android?
- AutoCompleteTextView - deshabilitar el filtrado
- Cómo filtrar ListView utilizando getFilter () en BaseAdapter
- Cómo implementar filtrado en RealmRecyclerViewAdapter
- Android ¿Cómo puedo sobrescribir el filtro para mi ArrayAdapter?
Su problema son estas líneas:
this.original = items; this.fitems = items;
Elementos es la lista que utiliza para su ListView y ponerla en dos variables diferentes no hace dos listas diferentes fuera de ella. Usted está dando solamente a los artículos de la lista dos nombres diferentes.
Puedes usar:
this.fitems = new ArrayList(items);
Que debe generar una nueva Lista y los cambios en esta lista solo cambiarán la lista de fitems.
Puede lograr el mismo efecto creando un método toString()
en su clase Pkmn que devuelve el valor que desea filtrar.
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 crear la nueva matriz de objetos para mostrar después del filtro (se puede encontrar una buena aplicación en el código fuente de la 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 utiliza el adaptador de matriz no puede hacer esto:
myAdapterData = results.values
Desde entonces se desconectan los datos de los superdatos, 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; }
- Insertar el año actual en un TextView
- ¿Cómo capturar eventos con el botón de hardware atrás en android?