Android. Custom ListView Filter. ListView в Android представляет собой список, которые можно наблюдать во множестве приложений - тот же Gmail, Twitter и так далее. В простейшем виде список содержит только текстовую информацию, однако, если помимо текста мы хотим отобразить в строке списка что-то еще, то чаще всего класс, отвечающий за показ данного списка приходится кастомизировать. Также зачастую бывает, что в данном списке необходимо что-то найти, например как в приложении контакты, когда по введенным буквам весь список фильтруется и в нем остаются лишь те контакты, которые содержат введенные нами буквы или цифры. Итак, как же это делается?
Итак, код нашего класса.
public class ShopAdapter extends ArrayAdapter<Shop> { private int layout; private Shop[] values; private Filter filter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { constraint = constraint.toString().toLowerCase(); FilterResults result = new FilterResults(); if (constraint != null && constraint.toString().length() > 0) { List<Shop> founded = new ArrayList<Shop>(); for (Shop t : values) { if (t.getAddress().toLowerCase().contains(constraint) || String.valueOf(t.getId()).contains(constraint)) founded.add(t); } result.values = founded; result.count = founded.size(); } else { result.values = null; result.count = 0; } return result; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { clear(); if (results.values == null) { for (Shop o : values) { add(o); } } else { for (Shop o : (List<Shop>) results.values) { add(o); } } notifyDataSetChanged(); } }; public ShopAdapter(Context context, Shop[] values, int layout) { super(context, layout, values == null ? new ArrayList<Shop>() : new ArrayList<Shop>()); for (Shop o : values) { add(o); } this.layout = layout; this.values = values; } public long getItemId(int position) { return getItem(position).getId(); } public static void fillView(Activity activity, final Shop item, final View v) { svUtils.fillTextView(activity, v, R.id.number, String.valueOf(item.getId())); svUtils.fillTextView(activity, v, R.id.address, item.getAddress()); } public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; LayoutInflater vi = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(layout, null); Shop item = (Shop) getItem(position); fillView(null, item, v); return v; } @Override public Filter getFilter() { return filter; } }
Начну с того, что класс, отвечающий за список будет наследоваться от класс ArrayAdapter<T>, обычно имплементируя свою реализацию адаптера, достаточно переопределить метод getView, однако, мы на этом не остановимся и переопределим метод getFilter, который будет возвращать класс нашего фильтра для нашей реализации списка. Как видно из кода, внутри класса ShopAdapter определяется еще один внутренний класс Filter, который в свою очередь наследуется от класса android.widget.Filter и реализует два метода. Первый метод отвечает за фильтрацию контента, содержащегося в нашем адаптере, второй метод отвечает за его публикацию. Обратите внимание, что на этапе создания нашего класса-адаптера в конструкторе создается дублирующая коллекция для хранения оригинальных результатов, тех, с которыми адаптер был создан, чтобы в любое время можно было вернуться к полному списку. В методе publishResults происходит очистка основной коллекции класса-адаптера от наших объектов, заполнение его новыми объектами и вызов события, говорящего, что содержимое изменилось и лист пора обновить.
Теперь осталось только подцепить это все в активити, для этого она должна содержать какой-то элемент ввода текста, чаще всего это EditText, к которому добавляется TextChangedListener, выглядит примерно так
filterText.addTextChangedListener(filterTextWatcher); private TextWatcher filterTextWatcher = new TextWatcher() { public void afterTextChanged(Editable s) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) {} public void onTextChanged(CharSequence s, int start, int before, int count) { adapter.getFilter().filter(s); } };
http://gobozov.blogspot.ru/2010/12/android-custom-listview-filter.html