DesarrolloLibre

Desarrollo Web, Android, juegos y mucho más

15-08-2016

En esta entrada veremos cómo crear un filtro para nuestros RecycleView; en una entrada anterior vimos cómo crear listados a través de listas y grids con el RecycleView hoy veremos el mismo proceso pero con un extra el cual consiste en crear un filtro para el listado anterior a través (lógicamente) por un campo de búsqueda con un simple EditText.

En nuestro adaptador crearemos una clase extra que llamaremos CustomFilter que lucirá de la siguiente manera:

public class CustomFilter extends Filter {
        private ListAdapter listAdapter;

        private CustomFilter(ListAdapter listAdapter) {
            super();
            this.listAdapter = listAdapter;
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            personsFilter.clear();
            final FilterResults results = new FilterResults();
            if (constraint.length() == 0) {
                personsFilter.addAll(persons);
            } else {
                final String filterPattern = constraint.toString().toLowerCase().trim();
                for (final Person person : persons) {
                    if (person.getName().toLowerCase().contains(filterPattern)) {
                        personsFilter.add(person);
                    }
                }
            }
            results.values = personsFilter;
            results.count = personsFilter.size();
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            this.listAdapter.notifyDataSetChanged();
        }
    }

Además de agregar un implements para implementar la clase Filterable en nuestro Adapter:

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> implements Filterable {
    private ArrayList<Person> persons;
    private ArrayList<Person> personsFilter;
    private CustomFilter mFilter;
...
}
public ListAdapter(ArrayList persons) {

    this.persons = persons;
    this.personsFilter = new ArrayList<>();
    this.personsFilter.addAll(persons);
    this.mFilter = new CustomFilter(ListAdapter.this);
}

En nuestro adaptador y el método asociado getFilter que sobreescribimos:

@Override
public Filter getFilter() {
    return mFilter;
}

Un pequeño dato que tenemos que hacer en nuestro adaptador es crear otra lista la cual contiene la data filtrada por el usuario y otro listado que contiene el total de la data que conforma nuestro listado sin aplicar ningún filtro; teniendo esto en cuenta nuestra el constructor y así como otros métodos de control quedaran definidos de la siguiente manera:

// Constructor
public ListAdapter(ArrayList persons) {

	this.persons = persons;
	this.personsFilter = new ArrayList<>();
	this.personsFilter.addAll(persons);
	this.mFilter = new CustomFilter(ListAdapter.this);
}
...
@Override
public int getItemCount() {
	return personsFilter.size();
}
...
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
	viewHolder.nameTextView.setText(personsFilter.get(position).getName());
	viewHolder.descriptionTextView.setText(personsFilter.get(position).getDescription());
	viewHolder.colorLl.setBackgroundColor(Color.parseColor(personsFilter.get(position).getColor()));
}

Cómo ves empleamos el ArrayList filtrable en vez del ArrayList completo.

Tenemos listo el adaptador, ahora falta configurar en nuestra actividad o fragment el campo de búsqueda para poder filtrar nuestro listado y los eventos asociados; para ello emplearemos un EditText como comentamos anteriormente:

etSearchBox = (EditText) findViewById(R.id.etSearchBox);

Y el evento escuchador (listener) que se activa al ingresar/remover texto sobre el mismo:

        etSearchBox.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                listAdapter.getFilter().filter(s.toString());
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });

Cómo puedes ver, al cambiar el texto se invoca el método filter pasando como parámetro el texto a filtrar.

Dato adicional

Puedes especificar el funcionamiento del filtro en la clase CustomFilter del adaptador definiendo el comportamiento en el momento en el que se realiza el llenado de personsFilter al realizar la comparación:

if (person.getName().toLowerCase().contains(filterPattern))

En nuestro caso nos interesa que NO sea sensible a mayúsculas/minúsculas y que contenga (contains) la palabra o sección clave y de esta forma tener un filtro bastante flexible, pero puedes expresarlo como desees.


Publicidad

Give me for a beer!

Algunos recursos que te pueden interesar

Editable Listview con jQuery

Editable Listview con jQuery

Generador de launcher para Android sin padding

Generador de launcher para Android sin padding

Templates para Android y iOS

Templates para Android y iOS

Algunos artículos que te pueden interesar

Dibujando un SeekBar personalizado en Android con Canvas

Dibujando un SeekBar personalizado en Android con Canvas

Se explica cómo crear un sencillo SeekBar mediante la API de Canvas en Android que consiste consiste de una barra lateral (un rectángulo achatado) y una circunferencia que hará la vez de control y es la que manipularemos mediante un clic.

Andrés Cruz 18-07-2017

Debugging de páginas web con Google Chrome y Android

Debugging de páginas web con Google Chrome y Android

Se explica cómo realizar el debugging de nuestras páginas web desde un dispositivo Android en nuestra PC.

Andrés Cruz 30-01-2017

Usar la consola de salida en Eclipse System.out.println y Log

Usar la consola de salida en Eclipse System.out.println y Log

La API de Android incorpora la clase Log para desplegar distinto tipos de información.

Andrés Cruz 13-02-2014