ViewPager
В Android есть компонент ViewFlipper, который позволяет прокручивать экран влево-вправо. Но он имеет ряд недостатков. ViewFlipper не позволяет с лёгкостью добиться эффекта привязки, когда экраны двигаются вместе с пальцем. Также нужен механизм автоматической доводки экранов в ту или иную сторону.
Google предложила другой вариант — использовать компонент ViewPager, который входит в состав Support Package. В новых проектах необходимая библиотека добавляется автоматически, поэтому мы сразу можем попробовать написать демонстрационный пример.
Так как компонент относится к пакету совместимости, то используемые фрагменты должны относиться к классу android.support.v4.app.Fragment, даже если вы собираетесь писать приложение для новых устройств, которые поддерживают стандартные фрагменты. На данный момент библиотека переписывается на AndroidX, поэтому я буду по возможности заменять старые примеры. Все названия классов и методов остаются, меняется только имя пакета.
ViewPager относится к категории ViewGroup и схож по работе с компонентами на основе AdapterView (ListView и Gallery). На панели инструментов Android Studio компонент можно найти в разделе Containers. При использовании ViewPager в разметке используйте полное имя класса. Старый вариант.
Данные для отображения компонент берёт из адаптеров:
- PagerAdapter (фрагменты не обязательны)
- FragmentPagerAdapter (если используется мало фрагментов)
- FragmentStatePagerAdapter (если много фрагментов)
Вам нужно унаследовать класс от нужного адаптера и реализовать свои методы. Добавление и удаление экранов реализуется с помощью методов instantiateItem() и destroyItem() соответственно. Элементы View для отображения можно создавать прямо в адаптере. Такой подход хорош тем, что ViewPager можно настраивать так, чтобы в адаптере не хранились все экраны сразу. По умолчанию адаптер хранит текущий экран, и по одному слева и справа от него. Это может сэкономить память, если содержание экранов слишком сложное.
Когда пользователь переключается на другой фрагмент, то вызывается метод onDestroyView(), а не onDestroy().
FragmentPagerAdapter
Рассмотрим простой пример с минимальным количеством кода для первого знакомства. Создадим новый проект. В activity_main.xml добавим ViewPager из примера выше.
Подготовим разметки для фрагментов.
Сначала создадим ещё один файл разметки res/layout/fragment_1.xml:
И ещё один файл res/layout/fragment_2.xml:
Создадим новый класс для первого фрагмента Fragment1:
Класс для второго фрагмента Fragment2:
Фрагменты подготовлены. Теперь в основном классе MainActivity создадим адаптер на основе FragmentPagerAdapter и напишем остальной код:
В методе getCount() следует возвращать количество страниц. В методе getItem() по номеру позиции нужно вернуть фрагмент.
Если у нас имеется три экрана, то может быть удобно сразу показать второй экран, чтобы можно было прокручивать или влево к первому экрану или вправо к третьему экрану. Это достигается вызовом метода setCurrentItem(1).
В нашем примере мне было лень создавать третий фрагмент, поэтому второй фрагмент используется два раза. В качестве фрагмента по умолчанию я установил первый фрагмент. Запустите пример и подвигайте экраны приложения вправо-влево.
Сам принцип теперь понятен? Нужно подготовить фрагменты и через адаптер сменять их.
PageTransformer
Если хочется добавить анимации при смене фрагментов, то воспользуйтесь специальным классом PageTransformer. Попробуем менять прозрачность фрагмента.
Класс PageTransformer заслуживает отдельной статьи.
PagerTitleStrip
Рассмотрим другой вариант и изучим другие возможности. Для примера будем использовать всего один фрагмент, содержимое которого будем менять динамически. А сверху добавим специальную полоску с заголовками.
Изменим разметку для фрагмента (fragment_1.xml):
Создадим два строковых массива в ресурсах (res/values/strings.xml):
Теперь подготовим класс для фрагмента CatFragment:
При создании фрагмент извлекает данные из объекта Bundle и использует их для заполнения текстов и картинки.
Создадим класс для адаптера в отдельном файле для удобства с помощью мастера создания класса, указав в качестве суперкласса FragmentPagerAdapter.
У адаптера должен быть пустой конструктор и два обязательных метода getItem() и getCount(). Немного переделаем конструктор, чтобы он использовал контекст, необходимый для извлечения данных из ресурсов.
Для подсчёта количества экранов используется свойство массива length. А для формирования содержимого экрана мы помещаем нужные данные в объект Bundle, которые затем будут переданы фрагменту. Данные находятся в трёх массивах: короткий текст, длинный текст и ссылка на изображение в ресурсах.
Метод getPageTitle() позволяет задать заголовок для фрагмента. Сам заголовок мы зададим в следующем шаге.
Приготовления почти закончены. Изменим разметку главной активности, чтобы у отдельного экрана появились заголовки. Для этого добавляется тег PagerTitleStrip:
Если вы хотите видеть заголовок внизу фрагмента, то используйте android:layout_gravity=»bottom».
Загружаем ViewPager и подключаем адаптер.
Пример на планшете в альбомной ориентации:
Свойства PagerTitleStrip можно изменить программно, например, поменять размер и цвет заголовков.
Тег PagerTitleStrip можно заменить на PagerTabStrip. В этом случае заголовке станут ещё и кнопками-вкладками. Ничего переписывать не придётся. Вы по-прежнему можете перелистывать страницы пальцами или нажимать на заголовки.
У ViewPager есть обработчик событий OnPageChangeListener с тремя методами:
Например, метод onPageSelected() позволяет получить номер текущего экрана при пролистывании (отсчёт от 0).
Метод onPageScrolled() даёт представление о текущем значении скрола при пролистывании.
Метод onPageScrollStateChanged() позволяет узнать о состоянии, в котором находится скрол (SCROLL_STATE_IDLE – экраны не листаются, SCROLL_STATE_DRAGGING – пользователь «тащит» страницу, SCROLL_STATE_SETTLING – палец пользователя «доводит» страницу до конца.
Сейчас данный слушатель помечен как устаревший.
Адаптер FragmentStatePagerAdapter
Это старый вариант примера, когда компонент только появился. Я не стал делать ревизию, оставляю вам для самостоятельного изучения.
Адаптер FragmentPagerAdapter держит все фрагменты в памяти, а FragmentStatePagerAdapter создаёт их заново по мере необходимости. В этом их принципиальное отличие. Напишем пример и добавим поддержку кнопки Back.
Создадим разметку для отдельной страницы (pager.xml):
Создадим класс фрагмента с минимальным кодом
Разметку активности оставим минимальной:
Код для активности. Тут всё уже знакомо.
Заключение
В Android Studio в некоторых шаблонах встречается реализация ViewPager из коробки. Недавно Гугл представила бета-версию ViewPager2, которая должна заменить старый компонент.
Источник
Перелистывание страниц и ViewPager2
ViewPager2 и разделение приложения на страницы
Нередко можно встретить приложения, которые реализуют систему перелистывания, а само приложение предстает в виде набора страниц, которые можно пролистывать влево и вправо. В приложении Android для создания подобного эффекта можно использовать элемент ViewPager2 из комплекта JetPack. Для создания эффекта страниц ViewPager2 использует фрагменты.
Итак, создадим новый проект. Добавим в папку res/layout файл разметки для фрагмента, который будет представлять страницу. Назовем его fragment_page.xml и определим в нем следующий код:
Фрагмент будет отображать текстовое поле с номером страницы.
Теперь добавим в проект сам класс фрагмента. Назовем его PageFragment :
Переменная pageNumber указывает на номер текущей страницы. Номер страницы будет передаваться извне через фабричный метод newInstance() . Передача номера происходит путем добавления значения в аргумент «num»
Затем при создании фрагмента в методе onCreate() этот номер будет извлекаться из аргумента «num» (если аргументы определены):
В методе onCreateView() полученный номер страницы будет отображаться в текстовом поле.
Сам по себе фрагмент еще не создает функциональность постраничной навигации. Для этого нам нужен один из классов PagerAdapter . Android SDK содержит ряд встроенных реализаций PagerAdapter, в частности, класс FragmentStateAdapter . Этот класс являются абстрактным, поэтому напрямую мы его использовать не можем, и нам нужно создать класс-наследник. Для этого добавим в проект новый класс, который назовем MyAdapter :
Класс FragmentStateAdapter определяет два метода:
int getItemCount() : возвращает количество страниц, которые будут в ViewPager2 (в нашем случае 10)
Fragment createFragment(int position) : по номеру страницы, передаваемому в качестве параметра position, возвращает объект фрагмента
Стоит отметить, что в качестве параметра конструктор FragmentStateAdapter принимает контекст выполнения — обычно это объект FragmentActivity, но также это может быть объект Fragment
В завершении установим в файле activity_main.xml элемент ViewPager2:
И также изменим код MainActivity :
Класс MainActivity наследуется от AppCompatActivity — класса, который в свою очередь наследуется от FragmentActivity, и поэтому ее текущий объект мы можем передать в качестве параметра в конструктор MyAdapter (а через него — в конструктор FragmentStateAdapter). Чтобы перелистывание заработало, для ViewPager2 устанавливается адаптер MyAdapter.
И запустив проект, мы сможем с помощью перелистывания перемещаться по страницам:
Источник
Перелистывание страниц android studio
Если вам нужно создать приложение с многими экранами, которые красиво переключаются между собой, то это можно довольно легко сделать с помощью такого стандартного элемента Android интерфейса, как ViewPager. ViewPager довольно прост в использовании и выглядит довольно красиво. В этом уроке мы создадим приложение с использованием ViewPager, в котором программно будут создаваться 5 экранов, на каждом из которых будет находится номер страницы и собственная фоновая картинка, а также сделаем так, что при нажатии на каждый из экранов будет появляться Toast сообщение с номером нажатой страницы.
Для начала создадим новое приложение, выбираем Blank Activity. Открываем файл activity_main.xml и задаем там ViewPager:
На этом настройка пользовательского интерфейса закончена. Все остальное будет происходить в файле MainActivity.java.
Для работы ViewPager ему нужно настроить собственный адаптер, унаследованный от PagerAdapter. Поэтому, в файле MainActivity.java до метода onCreate () мы задаем используемые объекты:
Теперь в методе onCreate () делаем стандартный шаг инициализации используемых объектов и настраиваем адаптер к ViewPager:
Ну и последний и самый важный шаг — это настройка того самого адаптера. Вся остальная работа будет проделана именно в теле адаптера.
Итак, мы создаем адаптер под названием MyPagerAdapter, наследуем его от PagerAdapter. Задаем целое число страниц в адаптере — 5, используемые картинки и цвета для каждого из 5 экранов в качестве двух массивов с данными. А далее программно создаем LinearLayout, задаем его параметры и цвет фона из массива цветов, созданных выше, и в теле этого layout также программно создаем 2 элемента: TextView и ImageView. Текстовое поле будет служить местом, где будет отображаться число — номер страницы, а в ImageView будет отображаться соответственная каждому экрану фоновая картинка.
Все это в коде выглядит следующим образом:
Вот и все, можно преступать к тестированию приложения с использованием такой крутой штуки как ViewPager:
Замечательно, все переключается, отображается и Toast сообщение не подвело.
Источник
Очень простой слайдер экранов
Когда я начинал изучать андроид, мне очень хотелось добавить красивое перелистывание экранов — как в популярных приложениях. Хотелось просто некоторое подобие LinearLayout, содержимое которого можно будет прокручивать. Однако для того, чтобы написать простейший слайдер с использованием ViewPager, мне потребовалось несколько часов на разбор, а также целая страница кода. К тому же, присутствовали некоторые ограничения — добавление объекта внутрь тега не добавляло его в список виджетов.
Разобравшись, решил написать свой класс ScreenPager, который наследуется от ViewPager и работает очень просто. Причём работает как в xml, так и в чистом коде.
Использование
Для начала создайте простейшее приложение. Пусть его класс MainActivity находится в com.example.testapp и имеет метод onCreate. Теперь создайте в том же каталоге класс ScreenPager и добавьте туда следующий код, не вникая в него пока что:
Теперь вы можете создать файл screenpager.xml в вашем res/layout и поместить туда следующий код
Если вы вручную создаёте файл — то не забудьте сохранить его в кодировке UTF-8. И не забывайте о том, что строки нужно сохранять в строковых ресурсах, а не вставлять напрямую. В данной статье я намеренно не делал это, чтобы упростить код.
Теперь в MainActivity.onCreate добавим одну строчку
Всё! Слайдер работает. Но длинное имя com.example.testapp — это некрасиво. Мы же хотим сделать всё максимально просто, не так ли?
Оказалось, что система позволяет использовать короткие имена только для классов из android.view или android.widget. Если же мы хотим сделать так для нашего класса — следует переопределить Factory для LayoutInflater. Я написал метод getShortNameFactory, который возвращает специальную фабрику, позволяющую использовать сокращённое имя для нашего класса. Установим её в методе onCreate, причём сделать это надо до setContentView:
Также импортируйте LayoutInflater, если ваша IDE не сделает это за вас:
Теперь мы можем использовать использовать сокращённое название нашего класса:
Но это ещё не всё! Вы можете строить ваши экраны в коде, и это тоже просто:
Используйте на здоровье. Вместо кнопок можете вставлять ваши менеджеры компоновки или любые другие is-a View объекты. Правда ваша среда разработки (в моём случае это Android Studio) может ругаться на отсутствие layout_width и layout_height, но это предупреждение можно легко отключить.
Подробности
Как работает ViewPager и PagerAdapter, можете почитать в этой статье. Собственно, я по ней их и изучал.
Класс ScreenPager наследуется от ViewPager и включает в себя нестатический вложенный класс — ScreenPagerAdapter, который наследуется от PagerAdapter. Если понадобится его получить — это можно будет сделать через getAdapter(). Также внутри ScreenPager находится список из View, с которыми он должен работать.
Когда обрабатывается xml-код, происходит вызов addView для каждого объекта внутри тега ScreenPager. Мы переопределили эту функцию и она перенаправляет View в addScreen, чтобы занести его в коллекцию и уведомить адаптер об этом. Таким образом, оба случая — и создание слайдера через код, и через xml — проходят через addScreen.
Источник