Списки(ListView) и сетки(GridView) . Свой дизайн элементов списка.

Home » android » Списки(ListView) и сетки(GridView) . Свой дизайн элементов списка.
android, Android Frontend, android service, GridView, ListView Комментариев нет

статья Simon Codrington – Custom Android Layouts with Your Own ArrayAdapter

В Android API есть целый набор различных лейаутов, подходящих под различные нужды приложений. Один из самых простых способов донести информацию о ряде каких-то объектов – компонент ListView. Этот компонент создает простую прокручиваемую область некоего набора данных. Самый большой плюс ListView – это настраиваемость, элемент списка можно настроить по своему усмотрению. Например, разместить в каждом элементе изображение, заголовок и текст определенным образом. Делается это с помощью пользовательских ArrayAdapter. В этой статье мы как раз разберем, как настроить свой класс, расширяющий ArrayAdapter.

Компоненты класса ArrayAdapter

Есть несколько связанных между собой элементов из которых, впоследствии собирается ListView.

Data Source – источник информации, список объектов
ArrayAdapter – объект в котором расписано, каким образом каждый объект DataSource, будет отображен как элемент ListView
ListView – объект пользовательского интерфейса, который использует адаптер для отображения информации в итоговом макете.

Если отобразить в виде схемы: необходим источник информации, адаптер, контролирующий отображение, и компонент в макете для отображения результата.

DataSource ArrayAdapter ListView
ArrayList Custom Adapter Final Visual Output
Object1
Object2
Object3
Преобразование каждого объекта в определенный xml-файл отображение готового списка в компоненте приложения(активности или фрагменте)

В качестве примера использования списка ListView вашему вниманию представляется фрагмент приложения, посвященного аренде отелей.(исходник на Git тут – Android 4.0.3 (API 15 – Ice Cream Sandwich)). В списке будет превью фотографии объекта аренды, информация о стоимости проживания, адрес арендуемого объекта и его описание.

Так выглядит конечный результат

listviewrental

Пример приложения

Не смотря на то, что автор щедро делится исходником приложения, он рекомендует, для понимания принципов, проработать код самостоятельно.

Определяем объект – источник информации

Перед тем как создать ListView вам нужна информация для отображения. Класс Property – это класс модели данных, содержащий все необходимые свойства объекта – единицы данных. В классе, для доступа к информации об объекте есть соответствующие геттеры и сеттеры.

Все поля – приватные, но доступны классическим образом через геттеры. Данные объекта создаются сразу, при инициализации объекта, в конструкторе.

Создадим файл XML-макета виджета элемента

Теперь, когда мы имеем элемент данных(класс модели), необходимо определить XML-файл макета элемента, который будет использоваться классом ArrayAdapter для отображения виджета элемента списка в макете приложения. Открываем res/layout проекта
Создаем новый файл макета property_layout и укажем RelativeLayout как коренной тег(можно, конечно, любой другой по вашему усмотрению).
Макет элемента делится на три секции:
Изображение – слева
Справа – адрес и описание
Подвал элемента содержит специфические данные объекта аренды – количество комнат, спален, санузлов, метраж, стоимость и т.д.
Макет элемента структурно выглядит примерно так:

макет виджета элемента

Приведем код элемента макета списка, по id атрибутам элементов макета видно, где в виджете будет выводиться информация. Понятно, что править макет можно по своему усмотрению.

В макет нашей активности(фрагмента) внесем элемент, в котором и будет выводиться наш список

Добавление изображений

Большинство компонентов пользовательского интерфейса элемента – текстовые, но в нашем макете элемента есть также и изображение.
В нашем примере мы будем использовать файлы изображений со схожими именами(property_image_1, property_image_2 […]). При построении списка объектов, в конструкторах передадим модели идентификаторы ресурсов, чтобы была возможность получить их адаптеру при рендеринге View-элемента.
Поместим изображения в папку drawable (копируем, вставляем(не перетаскиваем) и, при необходимости, синхронизируем проект (в Android Studio)).

listview_adding_images

Подготовка информации к использованию

Итак, у нас есть модель элемента информации, также есть XML-макет отображения виджета этой информации. Теперь нам необходимо создать полноценный источник информации, используя модель, создать коллекцию объектов и заполнить ее.

Создадим коллекцию объектов Property в нашей активности.

Затем заполним нашу коллекцию объектами

Конечно же, в реальном приложении, эта информация чаще всего берется с веб-сервера и объекты создаются на лету. В целях наглядности, DataSource этого примера довольно примитивен.

Создание своего класса ArrayAdapter

Стандартная реалзация ArrayAdapter позволяет выводить одну строку текста, для каждого элемента списка. Иногда достаточно и этого, но в большинстве ситуаций требуется создавать элементы списка по собственным макетам. Это можно сделать с помощью своей реализации класса ArrayAdapter.

В нашем примере, мы создадим класс ArrayAdapter как вложенный в MainActivity класс, в угоду наглядности. Понятное, дело, такое упрощение архитектуры не обязательно.

Итак, мы создали новый адаптер, под названием PropertyArrayAdapter и расширяющий ArrayAdapter.
Также, в нашей MainActivity, нам понадобятся две скрытые переменные экземпляра, – контекст и список объектов.

Конструктор ArrayAdapter

Так как наш класс расширяет ArrayAdapter, ему следует объявить какой-нибудь из конструкторов, принимающих аргументы: контекст, ресурс и объекты.

Этот конструктор, принимает на вход список объектов, а также контекст компонента, в котором будет реализован список. Оба важны и реализованы в классе как приватные переменные экземпляра.

Отрисовка View с помощью метода getView()

Если ListView требуется отрисовать элемент, он вызывает метод getView() адаптера. Если вам необходимо использовать свой шаблон отображения элемента списка, ва необходимо переопределить этот метод.

Если у вас есть доступ к позиции отрисовываемого элемента в списке List, вы можете получить его из списка объектов(который передается в адаптер через конструктор). Когда объект из списка получен, можно получить адрес, описание и стоимость и другие свойства объекта, с помощью соответствующих геттеров.

Загрузим наш XML файл макета.

Следующим шагом будет использование контекста(полученного в конструкторе), для получения LAYOUT_INFLATER_SERVICE сервиса.
Создаем объект LayoutInflater, его мы будем использовать для загрузки нашего XML-файла макета и отрисовки о этому макету элементов списка.

Populating the Layout File and Returning It
Так как у нас есть теперь доступ к XML-файлу макета, можно найти места элементов макета по их ID.
Получаем все View и затем наполняем их содержимым. Получаем поле адреса конкатенируя строки streetNumber, streetName и другие. Другие элементы отображаем в других View. Где необходимо, строки можно обрезать, чтобы они не превышали максимально допустимый объем в элементе макета и не вылазили за ограниченное им место.
Настройки изображения задаются несколько иначе, но не намного сложнее. Мы получаем из объекта имя изображения(например property_image_1). Затем, чтобы получить изображение из папки drawable мы последовательно используем методы getResources() и getIdentifier(). Мы получайм id ресурса, чтобы заполнить ImageView.

Можно упрощать адаптер и макет, или усложнять его, в любом случае принцип работы связки макет-адаптер-модель останется одним и тем же. Функциональность и подробность каждого элемента списка может быть, таким образом довольно просто осуществлена.

Использование своего ArrayAdapter

Теперь, когда у нас есть готовый класс ArrayAdapter, вернемся в метод onCreate() нашей активности.
Ниже того места, где мы добавили источник данных, создадим новый адаптер.

Еще раз разберем три параметра, которые имеет конструктор ArrayAdapter:

  • Текущий контекст(у нас это MainActivity class)
  • 0 в качестве значения id ресурса. Нам не нужен id ресурса своего макета, так как в нашем фиксируется в нашем адаптере
  • Список объектов для отображения в списке

Следующим шагом будет присоединение нового адаптера к ListView. Для этого просто надо применить к ListView метод setAdapter().

Готово!
Итак, при запуске приложения, мы увидем список, из элементов, собранных по кастомизированному макету и сконфигурированного с помощью собственного адаптера.

Бонус – загрузка макетов динамически

В примере выше мы отображали элемент списка с помощью файла макета property_layout.xml. Это простой способ, хорошо подходит, если нам нужно отображать все виджеты(элементы списка) одинаково.

Когда все View отрисовываются в ListView, вы можете выбрать какой макет использовать с помощью специального имени макета. Вы можете как загрузить новый макет для выбранного элемента(к примеру, для какого-то особого сложного элемента списка) или какую-то приспособленную версию для упрощенного элемента.
Вернемся к нашему примеру, чтобы реализовать в нем разные макеты для разных ситуаций.
Изменим класс модели, добавим в объект данных новое, особое поле.

Добавим геттер

public Boolean getFeatured(){return featured; }

Также следует добавить данную строку в конструктор, чтобы удостоверится в наличии этой дополнительной экстраинформации
You also need to add it to the constructor to ensure that the passed in data has this extra information.

К примеру, установим значение id равным 1, в одном из наших объектов списка.
Скопируем файл property_layout.xml и переименуем его в property_layout_alt.xml. Можно внести еще какие-нибудь изменения.
В классе MainActivity перейдем к методу getView() и изменим способ прорисовки XML файла.

В условной конструкции проверяем свойство featured, и при необходимости загружаем новый файл макета property_layout_alt.xml с нашими изменениями.

Запустим приложение. Вот как оно будет выглядеть с кастомным макетом для одного из элементов списка.
listviewdynamic_layout

Бонус: вешаем листенер кликов на элементы с помощью ArrayAdapter

Итак, наш контент представлен в виде аккуратного, красивого списка. Неплохо было бы сделать список интерактивным, чтобы, к примеру можно было бы переходить на активность подробного описания элемента.
Вернемся к методу onCreate нашей активности идобавим следующий код, перед закрывающей скобкой

Создаем новый объект onItemClickListener и имплементируем его метод onItemClick.
В этом примере мы беремм один из объектов аренды недвижимости, и помещаем некоторую Extra информацию в Intent. С этой информацией, мы можем перейти к новой активити Detail Activity, в котором детально раскроем информацию по элементу списка.
Когда пользователь щелкнет по элементу списка мы перекинем его на эту активити.
Обновим файл манифеста.

В этой активити мы получим из интента экстра-информацию о вызванном элементе списка.

Макет детальной активности

В дополнение ко всему следует сказать что ArrayAdapter может использоваться не только с ListView но также и с такими элементами макета как GridView или Spinner.
В то время как событием клика можно добавить интерактивность к списку. Можно также использовать другие события, например прокрутку, для того чтобы украсить анимацию прокрутки списка, не забудем также о swipe.

источник

LEAVE A COMMENT