Viewpager android studio это

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, которая должна заменить старый компонент.

Источник

Полный список

— разбираемся с ViewPager

ViewPager позволяет нам организовать удобный и красивый просмотр данных с возможностью перелистывания влево-вправо. Сам ViewPager отвечает за показ и прокрутку. Но ему нужен еще PagerAdapter, который отвечает за предоставление данных.

PagerAdapter – это базовый абстрактный класс, для которого разработчик дописывает реализацию так, как ему надо. Существует распространенная стандартная (частичная) реализация PagerAdapter, которая работает с фрагментами – это FragmentPagerAdapter. Разработчику остается только создать фрагмент и определить кол-во страниц.

Напишем простой пример и рассмотрим основные возможности ViewPager и FragmentPagerAdapter.

Project name: P1251_ViewPager
Build Target: Android 2.3.3
Application name: ViewPager
Package name: ru.startandroid.develop.p1251viewpager
Create Activity: MainActivity

Читайте также:  The amazing spider man 2 xbox 360 android

В main.xml пишем:

Только компонент ViewPager.

Здесь только TextView, который будет показывать содержимое страницы.

Метод newInstance создает новый экземпляр фрагмента и записывает ему в атрибуты число, которое пришло на вход. Это число – номер страницы, которую хочет показать ViewPager. По нему фрагмент будет определять, какое содержимое создавать в фрагменте.

В onCreate читаем номер страницы из аргументов. Далее формируем цвет из рандомных компонентов. Он будет использоваться для фона страниц, чтобы визуально отличать одну страницу от другой.

В onCreateView создаем View, находим на нем TextView, пишем ему простой текст с номером страницы и ставим фоновый цвет.

Т.е. на вход у нас идет номер страницы, а на выходе получаем фрагмент, который отображает этот номер и имеет случайный фоновый цвет.

Фрагмент готов, пишем MainActivity.java:

В onCreate создаем адаптер и устанавливаем его для ViewPager. Также для ViewPager создаем обработчик событий. Он имеет три метода:

onPageSelected – дает номер текущей отображенной страницы

onPageScrolled – достаточно сложно объяснить на словах. Метод дает нам представление о текущем значении скроллера при пролистывании. Рекомендую поставить там запись в лог, полистать и посмотреть, что получается.

onPageScrollStateChanged – сообщает нам о состоянии, в котором находится скроллер (SCROLL_STATE_IDLE – ничего не скролится, SCROLL_STATE_DRAGGING – пользователь «тащит» страницу, SCROLL_STATE_SETTLING – скроллер долистывает страницу до конца)

Класс FragmentPagerAdapter — абстрактный. Нам надо реализовать в нем пару методов. Для этого создаем класс MyFragmentPagerAdapter. В нем реализуем методы:

getItem – по номеру страницы нам надо вернуть фрагмент, используем наш метод newInstance

getCount – здесь мы должны возвращать кол-во страниц, используем константу

Все сохраняем и запускаем приложение.

Полистаем страницы, в логах видим:

onPageSelected, position = 1
onPageSelected, position = 2
onPageSelected, position = 3
onPageSelected, position = 4
onPageSelected, position = 3
onPageSelected, position = 2
onPageSelected, position = 1
onPageSelected, position = 0

Срабатывает обработчик перелистываний.

PagerTitleStrip

К ViewPager можно прикрутить элемент, который будет показывать заголовки – PagerTitleStrip.

Помещаем PagerTitleStrip внутрь ViewPager.

А в коде адаптера надо добавить метод getPageTitle, чтобы PagerTitleStrip знал какой текст показывать в заголовке. В класс MyFragmentPagerAdapter в MainActivity.java дописываем:

Будем возвращать просто «Title» и номер страницы

Сверху появились заголовки.

PagerTabStrip

Заголовки могут участвовать в навигации. Для этого используется компонент PagerTabStrip. Это аналог PagerTitleStrip, но при нажатии на заголовок он перелистывает страницу. Его встраивание полностью аналогично только что рассмотренному PagerTitleStrip

Он также требует от адаптера метод getPageTitle, который у нас уже реализован в MyFragmentPagerAdapter.

Понажимайте на левый и правый заголовки, страницы будут перелистываться.

Lifecycle

Давайте подробнее рассмотрим, что происходит с фрагментами в моменты перелистывания. Для этого перепишем PageFragment.java:

В onCreate мы добавили запись в лог и попытку чтения сохраненного значения из savedInstanceState.

В onSaveInstanceState сохраняем номер страницы.

В onDestroy просто пишем лог.

Тем самым мы увидим, пересоздается ли фрагмент и может ли он при этом восстанавливать сохраненные значения.

Все сохраним, запустим приложение.

Создался фрагмент для нулевой и первой страницы. Хотя видна сейчас только нулевая. Адаптер разумно заранее создает следующую к показу страницу, чтобы при пролистывании не было тормозов. Фрагменты создаются первый раз, вытаскивать из savedInstanceState нечего, поэтому видим savedPageNumber = -1.

Перелистнем на первую страницу

Читайте также:  Dz09 android bluetooth часы

onPageSelected, position = 1
onCreate: 2
savedPageNumber = -1

Первую показал, вторую заранее создал.

Перелистнем еще пару страниц

onPageSelected, position = 2
onCreate: 3
savedPageNumber = -1
onPageSelected, position = 3
onCreate: 4
savedPageNumber = -1

Все также и остается. Заметьте, что не срабатывает onDestroy. Т.е. все страницы не уничтожаются, а хранятся в памяти.

onPageSelected, position = 2
onPageSelected, position = 1
onPageSelected, position = 0

Т.к. не было никаких уничтожений, то нет и никаких созданий. Достает страницы-фрагменты из памяти и показывает.

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

Правда есть нюанс: хоть сами фрагменты и не уничтожаются, но уничтожается их View-структура и потом создается заново. Вставьте лог в метод onCreateView и убедитесь. Хранится структура только текущей страницы и по одной справа и слева. Это кол-во соседних страниц с сохраняемой View-структурой может быть настроено методом setOffscreenPageLimit.

FragmentStatePagerAdapter

Этот адаптер аналогичен FragmentPagerAdapter, он также работает с фрагментами. Но использует другие механизмы работы с страницами. Он не хранит страницы в памяти, а каждый раз создает их. Давайте используем его. Для этого надо в MainActivity.java просто заменить FragmentPagerAdapter на FragmentStatePagerAdapter в секции импорта и в описании класса MyFragmentPagerAdapter.

И все. Сохраняем, запускаем.

Открылась нулевая страница. В логах видим:

onCreate: 0
savedPageNumber = -1
onCreate: 1
savedPageNumber = -1

Перелистнем на первую страницу

onPageSelected, position = 1
onCreate: 2
savedPageNumber = -1

Пока что поведение не отличается от прошлого адаптера.

Перелистнем на вторую страницу.

onPageSelected, position = 2
onDestroy: 0
onCreate: 3
savedPageNumber = -1

Вот и отличие. Видим, что также открылась вторая страница, также создалась третья, но при этом уничтожилась нулевая.

Перелистнем на третью:

onPageSelected, position = 3
onDestroy: 1
onCreate: 4
savedPageNumber = -1

Та же ситуация: отобразилась третья, уничтожилась первая, создалась четвертая.

Перелистнем обратно на вторую:

onPageSelected, position = 2
onDestroy: 4
onCreate: 1
savedPageNumber = 1

Отобразилась вторая, уничтожилась четвертая, создалась первая (и прочла сохраненное значение из savedInstanceState).

Т.е. видно, что адаптер хранит только текущую страницу и по одной соседней (справа и слева), чтобы быстро можно было перелистнуть.

Можно сделать вывод. Этот адаптер не очень быстрый, он будет подтормаживать при многократном перелистывании в обе стороны, т.к. постоянно пересоздает страницы. Но при этом он требует минимум памяти. Т.е. он подходит для большого количества страниц. Например, просмотр писем, смс, страниц книги.

Используйте тот адаптер, который вам больше подходит в данной ситуации. Или наследуйте класс PagerAdapter и создавайте адаптер под свои нужды.

Программное перелистывание

Чтобы программно перелистнуть страницу ViewPager используйте метод setCurrentItem. А чтобы узнать текущую страницу — getCurrentItem.

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Оцените статью