Добавление фильтра к адаптеру ArrayAdapre

By | 05.03.2014

Иногда возникает необходимость фильтрования вывода адаптера ArrayAdapter, в элементе ListView. Это может потребоваться например при использовании поиска, когда результаты вывода в ListView должны соответствовать искомой строке. Сделать это можно через фильтр адаптера. Рассмотрим пример использования фильтра с использованием кастомного объекта Item в ArrayList<Item>.

Для начала необходимо имплементировать в адаптер интерфейс Filterable. А также нужно создать две переменные itemFilter — фильтр, dataOrigin — исходные данные. Делается это вот таким образом:

public class ListAdapter extends ArrayAdapter<String> implements Filterable {
private Filter itemFilter;
......
 
// метод используется для возвращения к исходной коллекции, т.е. мы
// отменяем результаты фильтра при помощи переданной переменной в атрибутах
public void resetData(ArrayList items) {
    data = items;
}
 
// вызов фильтра
@Override
public Filter getFilter() {
    if(itemFilter == null)
        itemFilter = new ItemFilter();
 
    return itemFilter;
}
 
// собственно сам фильтр
private class ItemFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();
 
        // constraint - параметр фильтра переданный через атрибуты
        if(constraint == null || constraint.length() == 0) {
            results.values = dataOrigin;
            results.count = dataOrigin.size();
        } else {
            // создаём коллекцию, в которой будут храниться отфильтрованные результаты
            List newList = new ArrayList();
 
            // проходимся по коллекции
            for(Item i : data) {
                // фильтруем данные
                // если имя (i.getName) приведённое в верхний регистра соответствует (contains) значению
                // переданному в constraint, тогда добавляем его в новую коллекцию
                if(i.getName().toUpperCase().contains(constraint.toString().toUpperCase()))
                    newList.add(i);
            }
 
            // возвращаем новую коллекцию
            results.values = newList;
            // и количество результатов
            results.count = newList.size();
        }
        return results;
    }
 
    // сохраняем результаты и информируем адаптер о том, что данные изменились (notifyDataSetChanged)
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        if(results.count == 0) {
            // notifyDataSetInvalidated();
            data = (List) results.values;
            notifyDataSetChanged();
        } else {
            data = (List) results.values;
            notifyDataSetChanged();
        }
    }
}

Теперь нужно вызвать фильтр:

itemsListAdapter.getFilter().filter("_характеристика для сортировки_");