Отображение списков в 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(); } }
Комментариев нет:
Отправить комментарий