ViewPager2基础介绍

2,913 阅读2分钟

ViewPager2

viewPager2现在已经发布到1.0.0-beta04,它相较于viewPager我认为比较重大的改善就是采用RecyclerView的Adapter,这使得它可以很方便的动态添加,移除,变更item,这在老版本的ViewPager中是比较麻烦的

使用

  1. 添加依赖
dependencies {
    implementation "androidx.viewpager2:viewpager2:1.0.0-beta04"
}
  1. layout中添加
<androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
  1. 添加具体的子layout布局
<?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>
  1. 为ViewPager2创建Adapter类,不同于ViewPager,我们可以使用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)

将ViewPager2和adapter关联

class MainActivity : AppCompatActivity() {

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

看起来是不是非常简单,使用方法基本和RecyclerView相同

垂直滑动

如果之前在viewpager中使用垂直滑动只能够用第三方库,现在使用ViewPager2,我们可以很方便的切换滑动方向

viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL

使用FragmentStateAdapter

一样可以在ViewPager2中搭配fragments使用

  • 首先,让我们创建一个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")}"
        }
    }
}
  • 然后创建一个Adapter
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
}
  • 然后在Ativity中绑定
viewPager2.adapter = ViewPagerFragmentStateAdapter(supportFragmentManager)

OnPageChangeCallback

如果用之前的viewPager,如果我们要添加监听器,是这样的:

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

不得不重写三个方法,而ViewPager2中,使用OnPageChangeCallback可以很方便的添加监听器

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

如何搭配tablayout

如果想要搭配tablayout,使用一个TabLayoutMediator类就可以了

TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = Card.DECK[position].toString()
        }.attach()

如何实现动态增添item

直接像RecyclerView一样动态添加,删除就可以了

adapter.notifyItemRangeInserted(position, count);
adapter.notifyItemRangeRemoved(position, count);
adapter.notifyItemMoved(fromPosition, toPosition);
adapter.notifyItemRangeChanged(position, count, payload);

item过渡动画:PageTransformer

当用户由一个item切换到另外一个item,可不可以有一些额外的动画呢。

基于ViewPager2.PagerTransformer可以实现这样的功能。

主要是创建一个类继承ViewPager2.PageTransformer,重写transformPage()这个方法,这个方法有两个参数,一个是View, 一个position(float),具体的使用就是position参数代表了此刻用户滑动到了哪个位置,然后根据这个位置position去计算你想要让View所做的变换,这些变换包括但不限于

  • rotation
  • translationX/Y
  • scaleX/Y

例如

private val mAnimator = ViewPager2.PageTransformer { page, position ->
        val absPos = Math.abs(position)
        page.apply {
            rotation = if (rotateCheckBox.isChecked) position * 360 else 0f
            translationY = if (translateY) absPos * 500f else 0f
            translationX = if (translateX) absPos * 350f else 0f
            if (scaleCheckBox.isChecked) {
                val scale = if (absPos > 1) 0F else 1 - absPos
                scaleX = scale
                scaleY = scale
            } else {
                scaleX = 1f
                scaleY = 1f
            }
        }
    }

之后再和viewPager绑定

viewPager.setPageTransformer(mAnimator)

项目:

  • google官方在github上有一个项目,展示了ViewPager2所能实现的一些相效果:google官方项目

参考文章: