- ScrollView и HorizontalScrollView
- Методы scrollBy() и scrollTo()
- ListActivity — создаём прокручиваемый список
- Список за пять минут
- Шаг первый
- Шаг второй
- Шаг третий
- Шаг четвёртый
- Шаг пятый
- Шаг шестой
- Обработка нажатий
- Долгое нажатие и удаление элемента списка
- Заключение
- Исходный код
- Своя разметка
- Переключаемся между двумя списками
- Прокручиваемый список ListView
- Адаптеры списков
- BaseAdapter
- Класс ListActivity
- Пример использования ListActivity
- Листинг активности MainActivity
- Листинг activity_main.xml
- Системные разметки
- Пример множественного выбора
- Листинг activity_main.xml
- Ресурсный файл
- Наборы данных ArrayMap, SparseArray
- Листинг активности
ScrollView и HorizontalScrollView
При большом количестве информации, которую нужно поместить на экране приходится использовать полосы прокрутки. В Android существуют специальные компоненты ScrollView и HorizontalScrollView, которые являются контейнерными элементами и наследуются от ViewGroup. Обратите внимание, что класс TextView использует свою собственную прокрутку и не нуждается в добавлении отдельных полос прокрутки. Но использование отдельных полос даже с TextView может улучшить вид вашего приложения и повышает удобство работы для пользователя.
На панели инструментов компоненты можно найти в разделе Containers.
В контейнеры ScrollView и HorizontalScrollView можно размещать только один дочерний элемент (обычно LinearLayout), который в свою очередь может быть контейнером для других элементов. Виджет ScrollView, несмотря на свое название, поддерживает только вертикальную прокрутку, поэтому для создания вертикальной и горизонтальной прокрутки необходимо использовать ScrollView в сочетании с HorizontalScrollView. Обычно ScrollView используют в качестве корневого элемента, а HorizontalScrollView в качестве дочернего. Можно и наоборот, пробуйте.
В в теле метода onCreate() создайте ссылку на элемент TextView, объявленный в XML-разметке, и запишите в него через метод setText() какой-нибуль длинный текст, который не поместится в видимые размеры экрана устройства:
Запустив проект, вы должны увидеть вертикальную и горизонтальную полосы прокрутки при попытке скролирования.
Если полосы прокрутки вас раздражают, то используйте атрибут android:scrollbars=»none», который скроет их.
По такому же принципу можете вложить ImageView, чтобы просматривать большие картинки:
Методы scrollBy() и scrollTo()
Вы можете программно прокручивать контент с помощью методов scrollBy() и scrollTo(). Например, можно организовать автоматическую прокрутку во время чтения. В нашем примере мы будем прокручивать контент с помощью трёх кнопок.
Сам код для методов:
Дополнительное чтение
Библиотека ParallaxScrollView с использованием эффекта параллакса. Вы прокручиваете длинный текст, а задний фон прокручивается чуть медленнее. Возможно, кому-то пригодится. Там же можно скачать готовое демо и просмотреть в действии.
Источник
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 представляет собой прокручиваемый список элементов. По сравнению с TextView и другими простыми элементами компонент ListView намного сложнее в использовании. Сложности связаны с тем, что программирование прокручиваемого списка включает определение интерфейса и формирование набора данных. За набор данных отвечает Adapter.
Адаптеры списков
Прежде чем говорить о ListView необходимо пару слов сказать об адаптерах, которые формируют данные для прокручиваемого списка. Адаптер выбирает по порядку предоставленные данные и размещает их в списке. При этом для списка ListView адаптер на лету создаёт компоненты TextView и помещает в них информацию в нужном виде. Исходные данные для списка могут быть определены как в массиве, так и в базе данных; для второго случая будет использоваться адаптер взаимодействия с сервером базы данных. Разработчик может создать свой собственный адаптер.
В системе существуют уже готовые адаптеры. Например, ArrayAdapter использует массив значений, а CursorAdapter работает с объектом типа Cursor, используемый в сервере базы данных. Ниже представлены готовые адаптеры :
• ArrayAdapter | адаптер из массива данных формирует массив компонентов TextView для списка ListView; |
• SimpleAdapter | адаптер формирует данные более сложной структуры; |
• ListAdapter | адаптер формирования данных для ListView; строго говоря, это класс-интерфейс, который можно использовать как в ArrayAdapter, так и в SimpleAdapter; |
• SpinnerAdapter | адаптер формирования данных для компонента Spinner; |
• CursorAdapter | адаптер формирует данные для ListView с использованием курсора (данные должны иметь колонку с наименованием «_id»); |
• ResourceCursorAdapter | адаптер дополняет свойства CursorAdapter и может создавать «виды» из ресурсов; |
• SimpleCursorAdapter | расширяет свойства ResourceCursorAdapter и формирует компоненты TextView/ImageView из содержащихся в курсоре столбцов; |
• HeaderViewListAdapter | расширенный вариант ListAdapter, когда в ListView определяются заголовки. |
Адаптер стандартного списка ArrayAdapter имеет конструктор следующего вида :
BaseAdapter
Основой представленных выше адаптеров является базовый абстрактный класс BaseAdapter. Если необходимо создать собственный адаптер, например, для специального управления данными или для кэширования с целью повышения производительности работы приложения, то можно использовать BaseAdapter, свойства которого можно расширить.
BaseAdapter содержит несколько методов, которые необходимо переопределить. Например, метод getCount() позволяет определить количество отображаемых объектов. Второй, и самый важный метод адаптера — это метод getView(). Данный метод вызывается для каждого элемента списка, чтобы получить информацию для отображения. Метод getVew() содержит параметр convertView, позволяющий использовать заново уже существующий элемент списка, который вышел из видимой области экрана. Если convertView не пустой, то он может быть использован заново, чтобы не грузить разметку списка, что способствует росту производительности.
Метод getView() возвращает View компонент, который фактически является контейнером ViewGroup, содержащий в себе другие компоненты, например, ImageView или TextView.
Класс ListActivity
Если основная функция активности связана с представлением списка и выбором из него определенного элемента, то можно класс активности наследовать от ListActivity, расширяющий (extends) свойства Activity. Это значительно упростит использование списка ListView.
Класс ListActivity содержит ListAdapter, ответственный за управление набором данных. Адаптер с набором данных должен быть определен в методе активности onCreate() вызовом метода setListAdapter(ListAdapter), получающий в качестве параметра объект адаптера.
Класс ListActivity имеет метод onListItemClick(), вызываемый при выборе одного из элементов списка. Этот метод позволяет получить доступ к выбранному элементу.
Пример использования ListActivity
Рассмотрим пример использования класса ListActivity. Для этого создадим новый модуль (Module) и назовем его p07listview. В этом модуле создадим список из текстовых записей. При выборе одного из элементов списка выведем сообщение Toast с соответствующим названием элемента. Ниже представлен листинг активности MainActivity.
Листинг активности MainActivity
В методе активности onCreate создается адаптер массива текстовых строк, который подключается к списку. Метод onListItemClick(), вызываемый при выборе элемента из списка, формирует и показывает сообщение Toast.
Android имеет некоторые предопределенные разметки адаптера. В активности примера применена разметка android.R.layout.simple_list_item1.
При использовании предопределенной разметки необходимо соответствующим образом определять идентификатор компонента ListView; он должен иметь значение «@android:id/list». В противном случае Android Studio выбросит Exception в режиме run-time с сообщением о несоответствии значения идентификатора компонента. Ниже представлен листинг описания интерфейса активности res/layout/activity_main.xml; интерфейс примера включает только один компонент типа ListView.
Листинг activity_main.xml
На следующем скриншоте представлен интерфейс стартованного примера после выбора одного из элементов списка. В нижней части отображается соответствующее сообщение Toast.
Системные разметки
В примере была использована готовая системная разметка android.R.layout.simple_list_item_1, состоящая из одного TextView. В этой разметке определен интерфейс компонента. Android Studio позволяет просмотреть исходный код этой разметки. Для этого следует установить курсор на simple_list_item_1 и нажать клавиши Ctrl+B. Ниже представлен листинг разметки :
В листинге в качестве разметки представлен один компонент TextView с набором атрибутов. Имеется несколько вариантов системных разметок :
android.R.layout.simple_list_item_2
состоит из двух компонентов TextView, расположенных друг над другом. Верхний играет роль заголовка, нижний – роль подтекста.
android.R.layout.simple_list_item_checked
используется компонент CheckedTextView, справа от которого будет находиться флажок выбора элемента.
android.R.layout.activity_list_item
используется компонент TextView, слева от которого располагается иконка ImageView с идентификатором android.resource.id.Icon.
Пример множественного выбора
В рассмотренном выше примере выбирался только один элемент из списка. Компонент ListView позволяет сделать не только единичный выбор, но и множественный. В этом случае необходимо использовать соответствующую разметку (simple_list_item_checked) и установить свойство ChoiceMode в описании интерфейса компонента равным multiplyChoice. Множественный выбор также можно установить программно при помощи метода setChoiceMode(ListView.CHOICE_MODE_MULTIPLE).
В основе примера множественного выбора элементов из списка будем использовать предыдущий пример p07listview. Необходимо внести изменения как в описание интерфейса, так и в описание активности. Теперь листинг описания интерфейса активности res/layout/activity_main.xml примет следующий вид :
Листинг activity_main.xml
В чем отличие данного описания интерфейса от предыдущего? В первую очередь изменение коснулось значения идентификатора объекта android:id, связанное с тем, что в этом примере активность будет наследоваться от обычного класса Activity, а не от ListActivity, как это было ранее. Кроме этого, добавлен атрибут множественного выбора android:choiceMode. Если не определить данный атрибут, и использовать разметку simple_list_item_checked, то невозможно будет выделить ни одного элемента из списка : перехватить нажатие на элементе списка можно, но установить флажок нельзя. При значении атрибута android:choiceMode равным «singleChoice» можно будет выбрать/выделить только один элемент из списка.
Ресурсный файл
Второе изменение в примере коснётся описания массива строк. Нехорошо описывать элементы массива в java-коде, как это было выполнено в предыдущем примере. Правильнее хранить их в ресурсных файлах. Тем более, что это удобнее с точки зрения локализации интерфейса. Найдем в проекте файл с ресурсами res/values/strings.xml и добавим туда массив строк с именами. В итоге должен получиться файл с таким содержимым :
Для чтения данного массива значений из ресурсного файла необходимо использовать следующее выражение :
Наборы данных ArrayMap, SparseArray
Прежде чем переходить к классу «активности» необходимо рассмотреть объекты формирования массивов элементов в Android. Поскольку мы будем использовать множественный выбор элементов, то набор выделенных записей необходимо где-то сохранить. Для этого будем использовать класс типа ArrayMap.
Android имеет собственную реализацию набора данных типа HashMap, это класс ArrayMap, использующий принцип «ключ-значение». В отличие от HashMap класс ArrayMap внутри содержит два массива : в первом массиве в отсортированном виде хранятся хэш-коды ключей, во втором массиве – ключи и значения. Вторым важным отличием ArrayMap является возможность использования прохода по индексам в цикле (это обеспечивается вторым внутренним массивом). Рекомендуется использовать ArrayMap при ограниченном количестве объектов в наборе, когда количество операций добавления элементов несущественно. Пример использования класса ArrayMap :
Помимо ArrayMap android включает в свою библиотеку классы типа SparseArray. Класс SparseArray подобен ArrayMap с той лишь разницей, что в качестве ключа используются примитивные типы. Библиотека android содержит несколько разновидностей класса ArrayMap для различных типов : LongSparseArray, SparseIntArray, SparseBooleanArray. В следующей таблице представлены соответствия классов ArrayMap и SparseArray объектам HashMap :
ArrayMap | HashMap |
SparseArray | HashMap |
SparseBooleanArray | HashMap |
SparseIntArray | HashMap |
SparseLongArray | HashMap |
LongSparseArray | HashMap |
Листинг активности
Класс активности MainActivity является наследником Activity. В активности набор записей из ресурсного файла сначала заносится в массив data. После этого массив используется при создании адаптера типа ArrayAdapter, который регистрируется в прокручиваемом списке listView вызовом метода setAdapter. К компоненту списка listView подключен слушатель выделения элемента. При выделении любой записи набора слушатель получает массив логических значений SparseBooleanArray и в цикле формирует строку сообщения с перечнем выбранных записей, которые отображает в Toast.
На следующем скриншоте представлен интерфейс примера с тремя выбранными записями, отображаемыми в сообщении Toast.
Продолжение статьи связано с настройкой интерфейса прокручиваемого списка ListView.
Источник