Pull to refresh

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

Reading time4 min
Views30K
Original author: Birju Vachhani

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


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


Новые фичи


  • Поддержка вёрстки справа налево,
  • Поддержка вертикальной ориентации,
  • Улучшенный PageChangeListener.

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



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:


Горизонтальный ViewPager2


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


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


viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL

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


Вертикальный ViewPager2


Использование 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. А до тех пор, хорошего всем кода!

Tags:
Hubs:
Total votes 6: ↑5 and ↓1+4
Comments3

Articles