Sử dụng ViewPager2

ViewPager2 được Google phát hành vào tháng 2 năm 2019. Bạn có thể tìm thêm thông tin về bản phát hành alpha tại đây. Hãy cùng xem ViewPager2 có gì mới mẻ ko nhé!

Các tính năng mới

  • Hỗ trợ bố trí từ phải sang trái
  • Hỗ trợ trượt theo chiều dọc
  • PageChangeListener đã được cải tiến tốt hơn

Một vài thứ đã được thay đổi

  • PagerAdapter đã được thay thế bằng RecyclerView.Adapter.
  • PagerAdapter cũng đã thay thế bằng FragmentStateAdapter.
  • Phiên bản ViewPager2 này được phát hành cho Android X, vì vậy nếu bạn muốn sử dụng nó thì dự án của bạn phải được chuyển sang Android X. Bây giờ thì bắt đầu sử dụng thôi!

Thêm Viewpager2 vào project

Thêm code bên dưới vào dependencies của file build.gradle

dependencies {
    implementation "androidx.viewpager2:viewpager2:1.0.0-alpha01"
}

Nhớ Sync project trước khi làm những việc tiếp theo nhé!

Cài đặt

Thêm Viewpager2 vào layout của bạn

<androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

Tạo layout cho các page con

<?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>

Tiếp theo, tạo file ViewPagerAdapter.kt. Rồi tạo Adapter cho ViewPager2 bằng cách sử dụng RecyclerView.Adapter

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)

Rất đơn giản! Nó cũng giống như việc tạo một Adapter cho RecyclerView vậy!

Cuối cùng là set adapter cho ViewPager2

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewPager2.adapter = ViewPagerAdapter()
    }
}

Kết quả sẽ trông như thế này:

Set up viewpager2 theo chiều dọc

Thông thường, chúng ta phải sử dụng thư viện bên thứ 3 để set cho Viewpager cuộn theo chiều dọc. Nhưng Viewpager2 đã hỗ trợ thuộc tính này. Chúng ta chỉ cần set như sau:

viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL

Và kết quả thu được sẽ như sau:

Sử dụng FragmentStateAdapter

Bạn có thể sử dụng fragments để làm page con như trong Viewpager phiên bản cũ. Trong trường hợp này, bạn sử dụng FragmentStateAdapter để set up cho Viewpager2.

Đầu tiên, bạn cần tạo các fragment

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")}"
        }
    }
}

Tiếp theo, tạo adapter cho ViewPager2.

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
}

Cuối cùng là set adapter cho Viewpager2

viewPager2.adapter = ViewPagerFragmentStateAdapter(supportFragmentManager)

OnPageChangeCallback

Trong ViewPager cũ, một interface OnPageChangeListner được sử dụng để nhận các sự kiện thay đổi, cuộn trang. chúng ta cần override cả ba phương thức (onPageScrollStateChanged, onPageScrolled, onPageSelected) ngay cả khi chúng ta không dùng hết cả 3 phương thức đó.

oldViewPager.addOnPageChangeListener(object:ViewPager.OnPageChangeListener{
    override fun onPageScrollStateChanged(state: Int) {
        // useless
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
        // useless too
    }

    override fun onPageSelected(position: Int) {
        // useful
    }
})

Bây giờ chúng ta có OnPageChangeCallback, một abstract class với các phương thức non-abstract. Điều đó có nghĩa là chúng ta không cần override tất cả các phương thức này, chúng ta chỉ cần override lên những phương thức chúng ta sẽ sử dụng mà thôi. Đây là cách chúng ta có thể đăng ký cho các sự kiện thay đổi / cuộn trang.

viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        // No boilerplate, only useful
    }
})