Android viewpager with layouts

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

— разбираемся с 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

В 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 дописываем:

Читайте также:  Death note тема для андроид

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

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

PagerTabStrip

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

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

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

Lifecycle

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

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

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

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

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

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

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

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

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 для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Урок 19. Как создать андроид-приложение с вкладками – TabLayout с ViewPager2 на Kotlin

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

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

Добавление TabLayout в макет разметки экрана

Чтобы добавить вкладки на экран, нужно открыть макет разметки и добавить компонент com.google.android.material.tabs.TabLayout в верхней части экрана:

Для корректного размещения нужно изменить компонент ViewPager2 – высоту укажем 0dp. Таким образом, высоту компонента будет регулировать корневой ConstraintLayout по заданным ограничениям. А вместо ограничения app:layout_constraintTop_toTopOf=»parent» поставим app:layout_constraintTop_toBottomOf=»@+id/tab_layout» – чтобы верх компонента ViewPager2 был ограничен не верхней границей родительского компонента, а нижней границей компонента TabLayout.

Рассмотрим подробнее компонент com.google.android.material.tabs.TabLayout. Свойство app:tabMode=»scrollable» обеспечивает размещение в видимой части экрана только нескольких вкладок, остальные будут доступны в процессе прокрутки. Если мы не укажем это свойство, то в видимой части экрана будут одновременно отображаться все вкладки, и при большом их количестве визуальное восприятие будет затруднено.

Свойство app:tabIndicatorColor=»@color/teal_200″ указывает цвет, а app:tabIndicatorHeight=»4dp» – толщину индикатора вкладки.

Далее идут свойства ширины – указываем по родителю – и высоты – указываем по содержимому.

Последние три свойства – ограничения верхней части и боковых сторон компонента по родителю.

Читайте также:  Как удаленно форматировать андроид

Реализация вкладок в MainActivity

Открываем класс MainActivity и пишем реализацию вкладок:

Источник

Как работать с ViewPager2

Прошло не так много времени с тех пор, как 7 февраля 2019 года Google выпустила альфа-версию Android ViewPager2. Более подробную информацию об этом релизе можно найти здесь. А сейчас давайте посмотрим, что из себя представляет ViewPager2.

Новые фичи

Что изменилось?

ViewPager2 выпущен для Android X, поэтому, если вы хотите его использовать, ваш проект должен использовать Android X. Давайте посмотрим, как мы можем использовать этот новый ViewPager2.

Добавление зависимости

Добавьте следующую зависимость в файл build.gradle на уровне приложения:

После этого синхронизируйте свой проект.

Настройка

Добавьте виджет ViewPager2 в вашу Activity или фрагмент:

Давайте создадим layout для страницы, которая будет отображаться во ViewPager2:

Далее нам нужно создать Adapter для ViewPager2. Это самая интересное. Для этого мы можем использовать RecyclerView.Adapter . Разве это не круто?

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

Последний шаг, установим адаптер для ViewPager2:

Вот и всё! Получаем тот же результат, как и при использовании старого ViewPager с PagerAdapter:

Вертикальная прокрутка

Раньше нужно было использовать сторонние библиотеки для реализации вертикальной прокрутки, т.к. до сих пор Google не предоставляла такой возможности «из коробки». В этом новом ViewPager2 теперь есть поддержка вертикальной прокрутки. Просто измените ориентацию во ViewPager2 и вертикальная прокрутка будет включена. Очень просто!

Вот, что получается в итоге:

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

Вы также можете использовать фрагменты в качестве страниц, как и в старом ViewPager. Для этого есть FragmentStateAdapter. Давайте посмотрим, как мы можем его использовать.

Прежде всего, нам нужно создать фрагмент:

Теперь мы создадим адаптер для ViewPager2. В его конструктор мы передадим FragmentManager, который будет управлять фрагментами:

Теперь установим этот новый адаптер во ViewPager2, и всё готово:

Улучшенный OnPageChangeCallback

В старом ViewPager интерфейс OnPageChangeListner был предназначен для получения событий изменения/прокрутки страницы. И это была очень неудобно, т.к. нам нужно было переопределять все три метода ( onPageScrollStateChanged , onPageScrolled , onPageSelected ), даже если мы этого не хотели.

Теперь у нас есть OnPageChangeCallback , абстрактный класс с неабстрактными методами. Что буквально означает, что нам не нужно переопределять все эти методы, мы можем просто переопределить те, которые нам нужны или которые мы хотим использовать. Вот так, например, мы можем отслеживать события смены страницы:

Внимание!

Поскольку ViewPager2 находится в альфа-версии, есть некоторые функции старого ViewPager, которые ещё не были реализованы или не работают должным образом в этой версии.

Известные проблемы согласно документации:

  • ClipToPadding,
  • Отсутствует интеграция с TabLayout,
  • Отсутствует контроль за пределами экрана,
  • Нельзя установить ширину страницы (100% по умолчанию)

Больше информации об известных проблемах — здесь. Надеюсь, что всё это будет исправлено в ближайших обновлениях. Я с нетерпением жду стабильной версии этого нового ViewPager2. А до тех пор, хорошего всем кода!

Источник

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