- ListActivity — создаём прокручиваемый список
- Список за пять минут
- Шаг первый
- Шаг второй
- Шаг третий
- Шаг четвёртый
- Шаг пятый
- Шаг шестой
- Обработка нажатий
- Долгое нажатие и удаление элемента списка
- Заключение
- Исходный код
- Своя разметка
- Переключаемся между двумя списками
- ListView
- Знакомьтесь — ListView
- Адаптеры — заполнение списка данными
- Отступление
- Собственная разметка
- android.R.layout.simple_list_item_1
- android.R.layout.simple_list_item_2
- android.R.layout.simple_list_item_checked
- android.R.layout.activity_list_item
- Динамическое заполнение списка
- Прослушивание событий элемента ListView
- Программное нажатие на элемент списка
- ListView не реагирует на нажатия
- Настраиваем внешний вид ListView
- Пользовательский селектор
- Множественный выбор
- Подсветка нажатий
- res/values/colors.xml
- res/drawable/item_selector.xml
- res/drawable-v21/item_selector.xml
- res/values-sw600dp/styles.xml
- Кнопка под списком
- Плавная прокрутка в начало списка или любую позицию
- Настраиваем прокрутку
- ListActivity
- Настройка цвета при достижении края прокрутки
- Нет данных для отображения
- Добавляем шапку и подвал
- res/layout/list_header.xml
- res/layout/list_footer.xml
ListActivity — создаём прокручиваемый список
Список за пять минут
Очень часто экран приложения состоит из обычного прокручиваемого списка. Например, это может быть список контактов, дни месяца, ассортимент товара, технические характеристики модели и так далее. Android позволяет создать такой список за пару минут.
В предыдущих примерах мы встречали в коде строчку public class HelloWorld extends Activity, что означало наследование от специального класса Activity или производных классов, например, AppCompatActivity. Существует ещё один специальный класс ListActivity, специально разработанный для списков.
Сейчас данный тип активности устарел, так как не слишком удобен для планшетов. Теперь предпочтительнее использовать ListFragment. Но в основе всё равно лежит компонент ListView и базовые приёмы работы не изменились. Изучив данный пример, вы без труда разберётесь и с другими формами отображения списков.
Шаг первый
Создадим новый стандартный проект. Мы знаем, что в проекте есть файл activity_main.xml, отвечающий за разметку элементов на экране. Класс ListActivity разработан таким образом, что на экране есть только прокручиваемый список и ему не нужна дополнительная разметка. Поэтому набираемся смелости, выбираем в папке res/layout файл activity_main.xml и удаляем его.
Шаг второй
Всё пропало! Теперь ничего не запустится! Don’t panic! Открываем java-файл и видим, что студия ругается на строчку setContentView(R.layout.activity_main);, что вполне объяснимо. Мы ведь только что сами удалили файл разметки. Ещё раз набираемся смелости и удаляем эту строчку, она там тоже больше не нужна.
Шаг третий
Теперь нужно поставить Android в известность, что мы собираемся использовать экран со списком, поэтому меняем в строчке public class ВашеНазваниеActivity extends AppCompatActivity слово AppCompatActivity (или Activity) на ListActivity. Если набирать вручную, то студия автоматически импортирует нужный класс.
В результате в секции import нашего файла появится новая строка. Там же мы увидим строку, которую можно безболезненно удалить:
Шаг четвёртый
Подготовительные работы закончены. Теперь пришло время подготовить данные для списка, чтобы отобразить их на экране. Создадим массив строк:
К слову сказать, вы можете создать массив строк в ресурсах, в этом случае вам будет проще редактировать список, не затрагивая код программы. Когда наберётесь опыта, то сами решите, какой вариант лучше.
Шаг пятый
А теперь начинается самое важное. У нас есть намерение создать экран со списком и сами слова для списка. Необходим некий посредник, который свяжет эти звенья в одно целое. Для подобных целей в Android существует понятие адаптера данных и его определение для работы с массивами строк выглядит так:
Адаптеру нужно от вас три вещи: явки, пароли, деньги , текущий контекст, идентификатор ресурса с разметкой для каждой строки, массив строк.
Мы можем ему предложить ListActivity в качестве текущего контекста (можно использовать ключевое слово this), готовый системный идентификатор ресурса и созданный массив строк. А выглядеть это будет так:
Обратите внимание на строчку android.R.layout.simple_list_item_1. В ней уже содержится необходимая разметка для отдельного элемента списка, которая состоит из одного компонента TextView. Если вас не устраивает системная разметка, то можете создать собственную разметку в xml-файле и подключить её. Об этом в следующий раз.
Шаг шестой
Осталось сделать заключительный штрих — подключить адаптер:
Запускаем проект и любуемся своим списком. Он прекрасно прокручивается и каждый пункт подсвечивается при нажатии.
Обработка нажатий
Но пока приложение никак не реагирует на наши нажатия. Исправим ситуацию. Нам нужно знать, на каком пункте списка осуществляется нажатие. У ListActivity есть специальный метод для таких случаев — onListItemClick(). Начинайте вводить первые символы названия метода и студия предложит вам подходящий вариант. Нажмите Enter на предложенном варианте и у вас появится заготовка.
У метода четыре параметра. Самым интересным является третий параметр position, который указывает на номер выбранного пункта списка.
Осталось только прописать код для события — давайте выведем всплывающее сообщение, которое будет содержать позицию выбранного элемента списка.
Отсчёт позиций идёт с нуля, поэтому я прибавляю единицу к номеру позиции, чтобы получить информацию в привычном виде.
Замурчательно. Но хочется узнать не номер выбранного пункта, а сам текст. У списка ListView есть специальный метод getItemAtPosition(position), возвращающий объект для заданной позиции. Перепишем код.
В данном случае мы используем первый параметр l, который отвечает за родительский компонент ListView. Возвращаемый объект нужно преобразовать в строку.
В тех методах, у которых нет в параметрах ссылки на ListView, мы можем получить доступ к списку через метод активности getListView().
Запускаем программу и начинаем щёлкать по любой позиции списка — мы получим соответствующее сообщение. Вы можете использовать свой код — вызывать новое окно, проигрывать музыку и т.д.
Долгое нажатие и удаление элемента списка
Расширим возможности списка и научимся обрабатывать долгие нажатия, а также удалять некоторые элементы списка.
Для долгого нажатия существует интерфейс OnItemLongClickListener с методом onItemLongClick(), возвращающим значение. Так как мы собираемся обрабатывать долгие нажатия, то строчку return false; необходимо заменить на return true;.
Добавляем интерфейс в активность, вручную вводя текст implements OnItem, студия предложит подсказку и поможет создать нужный метод для данного интерфейса.
Далее внесём небольшое изменение в адаптер данных. Сам по себе массив строк является неизменяемым, и чтобы мы могли удалять пункты из списка, необходимо сконвертировать его в специальный объект ArrayList , который является изменяемым, а уже новый объект отдадим адаптеру. Объявим новую переменную.
Подключаем к адаптеру.
Далее прописываем необходимый код для удаления выбранного пункта меню и запускаем программу. Прокручивая список, с удивлением замечаем, что среди кошачьих имён затесался какой-то сраный пёсик Бобик. Пробуем удалить его. Получилось! Теперь наш список выглядит правильно.
Метод remove() удаляет элемент из списочного массива, а метод notifyDataSetChanged() уведомляет список об изменении данных для обновления списка на экране.
На всякий случай ещё раз просмотрите список и если увидите чужеродное имя, то удалите его.
Удаление — весьма опасная операция, пользователь может по ошибке нажать на пункт списка. Лучшим решением было бы показать диалоговое окно с подтверждением операции. В последнее время весьма популярным стало использование специального типа уведомления внизу экрана с кнопкой «Отмена», например, готовый компонент SnackBar (о нём говорилось на одном из уроков).
Заключение
Поначалу эта статья может показаться вам сложной. Не отчаивайтесь, возьмите её как шаблон и на первых порах просто копируйте куски кода. Позже с практикой вы лучше разберётесь в работе со списком.
В данном материале вы познакомились с простым и быстрым способом создания списка на основе системных настроек. Но, если вам нужны более навороченные списки, то изучите статью про элемент управления ListView, а также статью Списки со значками.
Исходный код
Своя разметка
Когда в самом начале статьи я говорил, что для ListActivity не нужен шаблон activity_main.xml, то немножко лукавил. На самом деле вы можете подключить свой шаблон, но с одним условием — шаблон должен содержать элемент ListView с идентификатором @android:id/list.
Можно заново создать файл activity_main.xml, если вы его удалили, как вас просили, или файл с другим именем, например, activity_customlist.xml:
Я специально установил зелёный цвет для фона, чтобы вы поверили, что будет запускаться наш шаблон вместо системного, а TextView с системным идентификатором android:id/empty нужен для отображения текста, если список будет пустым. Осталось добавить строчку кода, который подключает шаблон:
Запустите проект и убедитесь, что загружается наш шаблон. Если вы зададите пустой массив, то вместо списка вы увидите TextView с текстом List is Empty.
Ещё раз напомню, что в стандартных списках отдельный его элемент представляет собой компонент TextView. Если вы хотите создать более сложную разметку с картинками, то вам надо изучить поближе ListView. Для этого на сайте есть отдельный раздел.
Переключаемся между двумя списками
Возможно, вам понадобится переходить из одного списка в другой. Например, первый список представляет собой месяцы, а второй — дни недели.
Мы создали два адаптера через массивы строк. Сначала используем первый адаптер. При выборе элемента списка через метод onListItemClick() подключаем другой адаптер. Чтобы изменения отразились на экране, необходимо вызвать метод notifyDataSetChanged().
Источник
ListView
Знакомьтесь — ListView
В ранних версиях Android компонент ListView был одним из самым популярных элементов интерфейса. Но теперь его время ушло, недаром на панели инструментов студии он находится в разделе Legacy (устаревший код).
ListView представляет собой прокручиваемый список элементов. Очень популярен на мобильных устройства из-за своего удобства. Даже кот способен пользоваться этим элементом, проводя лапкой по экрану вашего телефона.
Компонент ListView более сложен в применении по сравнению с TextView и другим простыми элементами. Работа со списком состоит из двух частей. Сначала мы добавляем на форму сам ListView, а затем заполняем его элементами списка.
Рассмотрим для начала самый простой пример. Поместите на форму компонент ListView и присвойте идентификатор. Вы увидите, что список будет содержать несколько элементов Item и Sub Item.
Однако, если посмотрим XML-код, то там ничего не увидим.
Переходим в класс активности и пишем следующий код:
Вот и всё. Давайте разберёмся с кодом.
Адаптеры — заполнение списка данными
Компоненту ListView требуются данные для наполнения. Источником наполнения могут быть массивы, базы данных. Чтобы связать данные со списком, используется так называемый адаптер.
Адаптер для стандартного списка обычно создаётся при помощи конструкции new ArrayAdapter(Context context, int textViewResourceId, String[] objects).
- context — текущий контекст
- textViewResourceId — идентификатор ресурса с разметкой для каждой строки. Можно использовать системную разметку с идентификатором android.R.layout.simple_list_item_1 или создать собственную разметку
- objects — массив строк
Метод setAdapter(ListAdapter) связывает подготовленный список с адаптером.
Переходим к java-коду. Сначала мы получаем экземпляр элемента ListView в методе onCreate(). Далее мы определяем массив типа String. И, наконец, используем адаптер данных, чтобы сопоставить данные с шаблоном разметки. Выбор адаптера зависит от типа используемых данных. В нашем случае мы использовали класс ArrayAdapter.
Отступление
Если вы будете брать строки из ресурсов, то код будет таким:
А будет еще лучше, если вы воспользуетесь специально предназначенным для этого случая типом ресурса . В файле res/values/strings.xml добавьте следующее:
И тогда в коде используйте для объявления массива строк:
Запустив проект, вы увидите работающий пример прокручиваемого списка. Правда, созданный список пока не реагирует на нажатия. Но при нажатии выбранный элемент выделяется цветным прямоугольником (в версии Android 2.3 был оранжевый, а в Android 4.0 — синий, потом был серый цвет и т.д.).
Собственная разметка
В примере мы используем готовую системную разметку android.R.layout.simple_list_item_1, в которой настроены цвета, фон, высота пунктов и другие параметры. Но нет никаких препятствий самому создать собственную разметку под своё приложение.
Но для начала неплохо бы взглянуть на содержание системной разметки. Студия позволяет увидеть исходный код, достаточно в коде поставить курсор на simple_list_item_1 и нажать на комбинацию клавиш Ctrl+B. Наш simple_list_item_1 выглядит так (в одной из версий):
Мы видим, что в качестве разметки используется TextView с набором атрибутов.
Если говорить о системных разметках, то имеется несколько вариантов. Вкратце ознакомимся с ними.
android.R.layout.simple_list_item_1
Состоит из одного TextView (см. выше)
android.resource.id.text1 |
android.R.layout.simple_list_item_2
Состоит из двух TextView — один побольше сверху и второй поменьше под ним.
android.resource.id.text1 |
android.resource.id.text2 |
android.R.layout.simple_list_item_checked
Справа от CheckedTextView будет находиться флажок
android.resource.id.text1 |
android.R.layout.activity_list_item
Слева от TextView находится значок ImageView с идентификатором android.resource.id.Icon.
android.resource.id.text1 |
Создадим свой шаблон для отдельного пункта списка. Для этого в папке res/layout/ создадим новый файл list_item.xml:
В некоторых случаях желательно установить атрибут android:background=»?android:attr/activatedBackgroundIndicator» у родительского элемента, чтобы элементы списка реагировали на нажатие изменением цвета. Можно задать и собственное поведение.
Вы можете настраивать все атрибуты у TextView, кроме свойства Text, так как текст будет автоматически заполняться элементом ListView программным путём. Ну, а дальше просто меняете в коде системную разметку на свою:
При создании собственного элемента списка, состоящего из TextView можете использовать специальный стиль для минимального размера текста.
Динамическое заполнение списка
Рассмотрим пример динамического заполнения списка, когда список изначально пуст и пользователь сам добавляет новые элементы. Разместим на экране текстовое поле, в котором пользователь будет вводить известные ему имена котов. Когда пользователь будет нажимать на клавишу Enter на клавиатуре, то введённое имя кота будет попадать в список.
При нажатии на Enter мы получаем текст из текстового поля и заносим его в массив. А также оповещаем адаптер об изменении, чтобы список автоматически обновил своё содержание.
У нас получился каркас для чата, когда пользователь вводит текст и он попадает в список. Далее надо получить текст от другого пользователя и также добавить в список. К слову сказать, слово chat с французского означает «кошка». Но это уже совсем другая история.
Прослушивание событий элемента ListView
Нам нужно реагировать на определенные события, генерируемые элементом ListView, в частности, нас интересует событие, которое возникает, когда пользователь нажимает на один из пунктов списка.
В этом нам поможет метод setOnItemClickListener элемента ListView и метод OnItemClick() интерфейса AdapterView.OnItemClickListener.
Теперь при нажатии на любой элемент списка мы получим всплывающее сообщение, содержащее текст выбранного пункта.
Естественно, мы можем не только выводить сообщения, но и запускать новые активности и т.п.
В метод onItemClick() передаётся вся необходимая информация, необходимая для определения нажатого пункта в списке. В приведенном выше примере использовался простой способ — приводим выбранный элемент к объекту TextView, так как известно, что в нашем случае все пункты являются элементами TextView (Для дополнительной проверки можете использовать оператор instanceOf). Мы извлекаем текст из выбранного пункта и сравниваем его со своей строкой.
Также можно проверять атрибут id для определения нажатия пункта списка.
Программное нажатие на элемент списка
Вдруг вам захочется программно нажать на элемент списка. Мы задали код, который будет выполняться при нажатии, в предыдущем примере. Теперь добавим кнопку и напишем код для щелчка.
Код громоздкий, но работоспособный.
ListView не реагирует на нажатия
В некоторых случаях нажатия на пунктах меню не срабатывают. Ниже приводятся несколько возможных причин.
Элемент списка содержит CheckBox, который также имеет свой слушатель нажатий. Попробуйте удалить фокус у него:
Попробуйте переместить OnItemClickListener перед установкой адаптера. Иногда помогает.
Элемент списка содержит ImageButton. Установите фокус в false:
Элемент списка содержит TextView. Если вы используете атрибут android:inputType=»textMultiLine», то замените его на android:minLines/android:maxLines.
Элемент списка содержит TextView, содержащий ссылку на веб-страницу или электронный адрес. Удалите атрибут android:autoLink.
Настраиваем внешний вид ListView
У ListView есть несколько полезных атрибутов, позволяющих сделать список более привлекательным. Например, у него есть атрибут divider, который отвечает за внешний вид разделителя, а также атрибут dividerHeight, отвечающий за высоту разделителя. Мы можем установить какой-нибудь цвет или даже картинку для разделителя. Например, создадим для разделителя цветовой ресурс с красным цветом, а также ресурс размера для его высоты:
Далее присвоим созданный ресурс атрибуту divider, а также зададим его высоту в атрибуте dividerHeight у нашего элемента ListView:
Если вас не устраивает стандартный разделитель, что можете нарисовать какую-нибудь волнистую черту, сохранить ее в PNG-файле и использовать как drawable-ресурс. Проделайте это самостоятельно.
Можно работать с данными атрибутами программно:
Если хотите убрать разделители, то используйте прозрачный цвет.
Заметил, что порядок вызова двух методов важен, если установку высоты вызвать перед установкой цвета разделителя, то метод затирает цвет и результат будет такой же, как с прозрачным цветом.
Обратите внимание, что по умолчанию разделитель не выводится перед первым и последним элементом списка. Если вы хотите изменить эти настройки, то используйте свойства Footer dividers enabled (атрибут footerDividersEnabled) и Header dividers enabled (атрибут headerDividersEnabled):
Пользовательский селектор
Мы уже видели, что по умолчанию выбранный элемент списка выделяется при помощи цветной полоски. Данный селектор также можно настроить через атрибут android:listSelector. Создайте какую-нибудь текстуру для селектора и привяжите его через ресурс. Вот образец текстурированного ореола желтого цвета для селектора.
Нужно подготовить сначала файл res/drawable/selector.xml:
Если вам нужно сразу подсветить нужный элемент списка при запуске программы, то используйте связку двух методов:
Множественный выбор
ListView позволяет выбирать не только один пункт, но и несколько. В этом случае нужно установить свойство Choice Mode в значение multiplyChoice, что соответствует атрибуту android:choiceMode=»multipleChoice».
Также множественный выбор можно установить программно при помощи метода setChoiceMode(ListView.CHOICE_MODE_MULTIPLE).
Теперь, если создать массив строк, например список продуктов для кошачьего завтрака, то получим следующий результат.
Осталось только программно получить отмеченные пользователем элементы списка. Вот мой список продуктов, который я хочу предложить коту. Надеюсь, ему понравится мой выбор. Выбранные элементы будем помещать в TextView:
Если нужно получить отдельно список выбранных и невыбранных элементов списка, то можно написать следующее:
Переменная checked будет содержать список выбранных элементов, а переменная unchecked — список невыбранных элементов.
Следует отметить, что в примерах использовался старый метод getCheckedItemPositions(), доступный с Android 1. В Android 2.2 появился новый метод getCheckedItemIds(). Учтите, что с новым методом можно получить массив только выбранных элементов, хотя в большинстве случаев этого достаточно. Но данный метод требует своих заморочек и в данном моём примере он не заработал.
Подсветка нажатий
На данный момент используется следующая техника подсвечивания элементов списка при нажатии. Здесь учитывается версия Android (до и после API 21).
res/values/colors.xml
res/drawable/item_selector.xml
res/drawable-v21/item_selector.xml
Разница заключается в том, что в версии 21 рекомендуется использовать серый цвет с применением ripple.
Созданные ресурсы следует применить для фона элемента списка (list_item.xml): android:background=»@drawable/item_selector».
Для проверки установим режим singleChoice для активации выбранного элемента списка.
Обычно режим активации выбранного элемента списка применяют для двухпанельной разметки, а в телефонах такой режим не используют. В таких случаях удобнее создать специальный стиль для списка.
Создадим стиль для планшетов.
res/values-sw600dp/styles.xml
А в обычном styles.xml оставим заглушку.
Теперь применим стиль к списку и нужное поведение с активацией будет применяться только на планшетах.
При повороте выбранный пункт списка может оказаться за пределами экрана. С помощью метода smoothScrollToPosition() мы можем автоматически прокрутить список к нужному месту. Код показан в продвинутых приёмах.
Кнопка под списком
Если вы хотите разместить кнопку под списком, которая бы не зависела от количества элементов в ListView, то воспользуйтесь весом (layout_weight).
Плавная прокрутка в начало списка или любую позицию
У списка есть специальный метод smoothScrollToPosition(), позволяющий плавно прокрутить до нужного места. Достаточно в методе указать номер позиции для прокрутки:
Учтите, что если элементов в списке несколько сотен и вы запустите плавную прокрутку указанным способом, то процесс может растянуться надолго. Например, коты могут и заснуть, не дождавшись конца операции. Задумайтесь.
Настраиваем прокрутку
У ListView есть атрибуты для настройки внешнего вида полосы прокрутки
Аналогично это применимо к полосам прокрутки у ScrollView, EditText и т.д.
ListActivity
Если вам нужна форма, состоящая только из списка, то вам проще воспользоваться системным классом ListActivity вместо стандартного Activity. Именно такой подход описан в документации по ListView. Пример работы описан в статье ListActivity — создаём прокручиваемый список.
Настройка цвета при достижении края прокрутки
Когда прокрутка достигает конца (сверху или снизу), то выводится цветовой эффект. В API 21 появилась возможность управлять этим эффектом через атрибут colorEdgeEffect:
Далее применяем как тему.
Для более старых устройств такую настройку сделать нельзя.
Нет данных для отображения
Если адаптер не содержит данных для отображения, то можете вызвать метод для показа пустой разметки:
Добавляем шапку и подвал
В подвалах часто живут коты, поэтому списки желательно также снабжать подвалом (и шапкой). У ListView есть такая возможность, давайте воспользуемся этим.
Элементами шапки и подвала могут послужить View, которые могут быть добавлены к списку сверху и снизу через методы addHeaderView() и addFooterView(). В принципе оба элемента одинаковы, только добавляются в разные места списка.
Полный варианты методов:
- v – компонент, который отобразится, как пункт списка
- data – объект, связанный с этим пунктом списка
- isSelectable – можно ли будет кликать на пункт или выделять его
Интересно, что до версии API 19 шапку и подвал можно было добавлять только до присвоения списку адаптера, иначе возникала ошибка. Теперь можно добавлять в любое время, ошибки не будет и список будет работать.
Для демонстрации подойдёт любой урок со списком. Дополнительно добавим два файла для шапки и подвала (можно также воспользоваться системной разметкой). Если по структуре шапка и подвал одинаковы, то можно обойтись и одним файлом. Но для разнообразия сделаем их немного разными.
res/layout/list_header.xml
res/layout/list_footer.xml
Осталось подключить шапку и подвал к списку. Напоминаю, что можете использовать любой пример со списком. Поэтому часть кода опущу.
Никто не запрещает использовать несколько шапок и подвалов в списке. Соответствующий код закомментирован.
Шапка состоит из двух текстовых меток. В первой метке текст задан в макете, а во второй текст устанавливается программно. Подвал сделан ещё проще — только одна метка, текст задан в макете. Естественно, вы можете реализовать более сложный макет в вашем приложении.
Шапку и подвал можно удалить программно через методы removeHeaderView() и removeFooterView().
Источник