DesarrolloLibre

Desarrollo Web, Android, juegos y mucho más

Categorias
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

Creando increibles Drawer en Android con MaterialDrawer

Creando increibles Drawer en Android con MaterialDrawer

Templates para Android y iOS

Templates para Android y iOS

Generador de launcher para Android sin padding

Generador de launcher para Android sin padding

Algunos artículos que te pueden interesar

Usando el ProgressBar en Android para indicar procesos de carga

Usando el ProgressBar en Android para indicar procesos de carga

En esta entrada se habla sobre un método para indicar el progreso de carga de una operación que puede sustituir al ProgressDialog llamado ProgressBar.

Andrés Cruz 07-11-2017

Primeros pasos con Wikitude en Android (parte 1)

Primeros pasos con Wikitude en Android (parte 1)

Se explica como dar los primeros pasos con Wikitude con la cual podemos crear aplicaciones con realidad aumentada con Android Studio, IOS, PhoneGap; se explica como descargar e instalar la SDK de Wikitude en Android Studio.

Andrés Cruz 25-05-2017

Construyendo nuestro propio logo Android con SVG en HTML

Construyendo nuestro propio logo Android con SVG en HTML

En esta entrada abordaremos un tema un poco más práctico y veremos cómo construir nuestro propio logo de Android empleando lo hablado hasta el momento.

Andrés Cruz 21-05-2015