Отображение списков в Android можно реализовать с помощью ListView компонента. Иногда возникает необходимость использовать разные типы элементов списка, которые различаются разметкой, ролью, поведением и так далее. Например, нужно разделить список на секции с соответствующими заголовками, в одном элементе нужно отображать количество новых сообщений, а в другом должен быть CheckBox компонент. В некоторых случаях подходит ExpandableListView, но при этом может не подходить его поведение, а именно разворачивание и сворачивание групп при нажатии. Так же не понятно как реализовать визуализацию разной разметки элементов. Мы же рассмотрим, как использовать ListView с различными типами элементов, и каким должен быть адаптер данных, который играет в этом важную роль.
Интерфейс элементов
Сначала нужно создать интерфейс, который будут реализовать классы разных элементов. Этот позволят обращаться к элементам одинаково и хранить их в одном списке или массиве. В тоже время классы будут реализовать его по-разному в соответствии с данными. Пример интерфейса:
Item.java
public interface Item {
public int getViewType();
public View getView(LayoutInflater inflater, int position, View convertView);
public long getId();
public boolean isEnable();
}
Метод getViewType() возвращает тип элемента, getView() создает и возвращает View элемента, метод getId() возвращает идентификатор и метод isEnable() говорит о том, будет ли элемент списка активным, если вернуть false, то на элемент нельзя будет нажать и соответственно не будет события нажатия.
Реализация интерфейса
Для каждого типа элемента нужно создать класс и реализовать интерфейс. При этом класс отвечает за разметку, представление, поведение и хранение соответствующих данных, тем сам мы избавляемся от анализа типа при визуализации и множества других условий. Ниже приведены класс с реализацией нашего интерфейса:
HeaderItem.java
public class HeaderItem implements Item {
HeaderData item;
public HeaderItem(HeaderData item) {
this.item = item;
}
@Override
public int getViewType() {
return RowType.HEADER_ITEM.ordinal();
}
@Override
public View getView(LayoutInflater inflater, int position, View convertView) {
// создаем View с определенной разметкой и атрибутами
// Возвращаем View элемента заголовка
return convertView;
}
@Override
public long getId() {
return 0;
}
@Override
public boolean isEnable() {
return false;
}
}
TextItem.java
public class TextItem implements Item {
private TextData item;
public TextItem(TextData item) {
this.item= item;
}
@Override
public int getViewType() {
return RowType.TEXT_ITEM.ordinal();
}
@Override
public View getView(LayoutInflater inflater, int position, View convertView) {
// Создаем View с определенной разметкой и атрибутами
// Возвращаем View обычного элемента
return convertView;
}
@Override
public long getId() {
return mItem.programItem.get_id();
}
@Override
public boolean isEnable() {
return true;
}
}
Адаптер
В качестве адаптера лучше использовать ArrayAdapter или BaseAdapter, которые обладают двумя очень важными методами. Первый метод getItemViewType(), который возвращает тип элемента в будущем созданного в getView(int, View, ViewGroup) методе. Второй метод getViewTypeCount(), возвращает количество типов элементов в будущем созданных в getView(int, View, ViewGroup) методе. Для определения типов можно использовать Enum и для количества типов метод values() совместно со свойством length. Адаптер выглядит следующим образом:
ListItemsAdapter.java
public class ListItemsAdapter extends ArrayAdapter<Item> {
protected static LayoutInflater mInflater;
public enum RowType {
HEADER_ITEM, TEXT_ITEM
}
public ListItemsAdapter(Context context, List<Item> items) {
super(context, 0, items);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getViewTypeCount() {
return RowType.values().length;
}
@Override
public int getItemViewType(int position) {
return getItem(position).getViewType();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getItem(position).getView(mInflater, position, convertView);
}
@Override
public long getItemId(int position) {
return getItem(position).getId();
}
@Override
public boolean isEnabled(int position) {
return getItem(position).isEnable();
}
}
Комментариев нет:
Отправить комментарий