Android. Custom ListView Filter.
ListView в Android представляет собой список, которые можно наблюдать во множестве приложений - тот же Gmail, Twitter и так далее. В простейшем виде список содержит только текстовую информацию, однако, если помимо текста мы хотим отобразить в строке списка что-то еще, то чаще всего класс, отвечающий за показ данного списка приходится кастомизировать. Также зачастую бывает, что в данном списке необходимо что-то найти, например как в приложении контакты, когда по введенным буквам весь список фильтруется и в нем остаются лишь те контакты, которые содержат введенные нами буквы или цифры. Итак, как же это делается?
Итак, код нашего класса.
public class ShopAdapter extends ArrayAdapter {
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 founded = new ArrayList();
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) results.values) {
add(o);
}
}
notifyDataSetChanged();
}
};
public ShopAdapter(Context context, Shop[] values, int layout) {
super(context, layout, values == null ? new ArrayList()
: new ArrayList());
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//, обычно имплементируя свою реализацию адаптера, достаточно переопределить метод 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]]