Прошло не так много времени с тех пор, как 7 февраля 2019 года Google выпустила альфа-версию Android ViewPager2. Более подробную информацию об этом релизе можно найти здесь. А сейчас давайте посмотрим, что из себя представляет ViewPager2.
Новые фичи
- Поддержка вёрстки справа налево,
- Поддержка вертикальной ориентации,
- Улучшенный
PageChangeListener
.
Что изменилось?
- PagerAdapter заменён на RecyclerView.Adapter,
- FragmentStatePagerAdapter заменён FragmentStateAdapter.
ViewPager2 выпущен для Android X, поэтому, если вы хотите его использовать, ваш проект должен использовать Android X. Давайте посмотрим, как мы можем использовать этот новый ViewPager2.
Добавление зависимости
Добавьте следующую зависимость в файл build.gradle
на уровне приложения:
dependencies {
implementation "androidx.viewpager2:viewpager2:1.0.0-alpha01"
}
После этого синхронизируйте свой проект.
Настройка
Добавьте виджет ViewPager2
в вашу Activity или фрагмент:
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Давайте создадим layout для страницы, которая будет отображаться во ViewPager2:
item_page.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvTitle"
android:textColor="@android:color/white"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
tools:text= "item"
android:textSize="32sp"
android:layout_height="wrap_content" />
</RelativeLayout>
Далее нам нужно создать Adapter для ViewPager2. Это самая интересное. Для этого мы можем использовать RecyclerView.Adapter
. Разве это не круто?
ViewPagerAdapter.kt
class ViewPagerAdapter : RecyclerView.Adapter<PagerVH>() {
private val colors = intArrayOf(
android.R.color.black,
android.R.color.holo_red_light,
android.R.color.holo_blue_dark,
android.R.color.holo_purple
)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerVH =
PagerVH(LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false))
override fun getItemCount(): Int = colors.size
override fun onBindViewHolder(holder: PagerVH, position: Int) = holder.itemView.run {
tvTitle.text = "item $position"
container.setBackgroundResource(colors[position])
}
}
class PagerVH(itemView: View) : RecyclerView.ViewHolder(itemView)
Это такой же адаптер, который мы используем для обычного RecyclerView, и с ViewPager2 он работает так же хорошо.
Последний шаг, установим адаптер для ViewPager2:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewPager2.adapter = ViewPagerAdapter()
}
}
Вот и всё! Получаем тот же результат, как и при использовании старого ViewPager с PagerAdapter:
Вертикальная прокрутка
Раньше нужно было использовать сторонние библиотеки для реализации вертикальной прокрутки, т.к. до сих пор Google не предоставляла такой возможности «из коробки». В этом новом ViewPager2 теперь есть поддержка вертикальной прокрутки. Просто измените ориентацию во ViewPager2 и вертикальная прокрутка будет включена. Очень просто!
viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL
Вот, что получается в итоге:
Использование FragmentStateAdapter
Вы также можете использовать фрагменты в качестве страниц, как и в старом ViewPager. Для этого есть FragmentStateAdapter. Давайте посмотрим, как мы можем его использовать.
Прежде всего, нам нужно создать фрагмент:
class PagerFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.item_page, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
arguments?.let {
container.setBackgroundResource(it.getInt("color"))
tvTitle.text = "Item ${it.getInt("position")}"
}
}
}
Теперь мы создадим адаптер для ViewPager2. В его конструктор мы передадим FragmentManager, который будет управлять фрагментами:
class ViewPagerFragmentStateAdapter(fm: FragmentManager) : FragmentStateAdapter(fm) {
private val colors = intArrayOf(
android.R.color.black,
android.R.color.holo_red_light,
android.R.color.holo_blue_dark,
android.R.color.holo_purple
)
override fun getItem(position: Int): Fragment = PagerFragment().apply {
arguments = bundleOf(
"color" to colors[position],
"position" to position
)
}
override fun getItemCount(): Int = colors.size
}
Теперь установим этот новый адаптер во ViewPager2, и всё готово:
viewPager2.adapter = ViewPagerFragmentStateAdapter(supportFragmentManager)
Улучшенный OnPageChangeCallback
В старом ViewPager интерфейс OnPageChangeListner
был предназначен для получения событий изменения/прокрутки страницы. И это была очень неудобно, т.к. нам нужно было переопределять все три метода (onPageScrollStateChanged
, onPageScrolled
, onPageSelected
), даже если мы этого не хотели.
oldViewPager.addOnPageChangeListener(object:ViewPager.OnPageChangeListener{
override fun onPageScrollStateChanged(state: Int) {
// бесполезный метод
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// тоже бесполезный
}
override fun onPageSelected(position: Int) {
// метод, который нам нужен
}
})
Теперь у нас есть OnPageChangeCallback
, абстрактный класс с неабстрактными методами. Что буквально означает, что нам не нужно переопределять все эти методы, мы можем просто переопределить те, которые нам нужны или которые мы хотим использовать. Вот так, например, мы можем отслеживать события смены страницы:
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
// Теперь только необходимое
}
})
Внимание!
Поскольку ViewPager2 находится в альфа-версии, есть некоторые функции старого ViewPager, которые ещё не были реализованы или не работают должным образом в этой версии.
Известные проблемы согласно документации:
- ClipToPadding,
- Отсутствует интеграция с TabLayout,
- Отсутствует контроль за пределами экрана,
- Нельзя установить ширину страницы (100% по умолчанию)
Больше информации об известных проблемах — здесь. Надеюсь, что всё это будет исправлено в ближайших обновлениях. Я с нетерпением жду стабильной версии этого нового ViewPager2. А до тех пор, хорошего всем кода!