Android Banner - ViewPager2 01

今天我们使用ViewPager2 实现一个banner

ViewPager2 对比 ViewPaer,支持横向和竖向的滚动。(大家也可以尝试使用RecyclerView实现Banner)

主要实现的功能和viewpager实现相同

  1. 无限轮播
  2. 代码抽取
  3. 动效
  4. 动态更新(插入或删除单个数据)

首先,viewpager2这个类被final修饰,意味着,我们不能使用继承的方式来扩展这个类,只能使用聚合的方式来处理(继承其他类,来添加viewpager2)

VP2Banner

我们使用FrameLayout作为父布局,包裹ViewPager2,方便后续扩展(比如加导航点)

class VP2Banner : FrameLayout {

    private lateinit var viewPager2: ViewPager2

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attributeSet: AttributeSet?) : this(context,
        attributeSet, 0)

    constructor(context: Context, attributeSet: AttributeSet?, style: Int) : this(
        context, attributeSet, style, 0)

    constructor(context: Context, attributeSet: AttributeSet?, style: Int, styleRes: Int) : super(
        context, attributeSet, style, styleRes) {
        // 初始化view,添加viewpager2到容器内部
        viewPager2 = ViewPager2(context)
        // 处理自定义属性

        // 添加viewpager2
        addView(viewPager2)
    }
}

VP2Adapter

ViewPager2基于RecyclerView实现的,所以它的adapter也是和RecyclerView的使用一样。

abstract class VP2Adapter<T, H : RecyclerView.ViewHolder>(private val loop: Boolean) :
    RecyclerView.Adapter<H>() {
    private val mData = mutableListOf<T>()
    private var mListener: ClickListener<T>? = null
    fun setData(data: List<T>) {
        mData.clear()
        if (loop && mData.size > 1) {
            mData.add(data[data.size - 1])
            mData.addAll(data)
            mData.add(data[0])
        } else {
            mData.addAll(data)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): H {
        val holder = createHolder(parent, viewType)
        holder.itemView.setOnClickListener { view ->
            mListener?.let {
                val position = holder.adapterPosition
                it.onClick(position, mData[position])
            }
        }
        return holder
    }

    override fun getItemViewType(position: Int) = getItemType(position)

    override fun getItemCount(): Int = mData.size

    override fun onBindViewHolder(holder: H, position: Int) {
        bindData(holder, mData[position])
    }

    abstract fun bindData(holder: H, data: T)

    abstract fun getItemType(position: Int): Int

    abstract fun createHolder(parent: ViewGroup, viewType: Int): H


    interface ClickListener<T> {
        fun onClick(position: Int, data: T)
    }
}

无限循环

和使用ViewPager实现方式一致,不再描述

单页显示多个

    fun setPageMargin(width: Int) {
        val realWidth = dp2px(width + 0F).toInt()
        viewPager2?.setPageTransformer(MarginPageTransformer(realWidth))
        viewPager2?.let { vp ->
            val recyclerView = vp.getChildAt(0) as? RecyclerView
            recyclerView?.let { rv ->
                rv.setPadding(realWidth+40, 0, realWidth+40, 0)
                rv.clipToPadding= false
            }
        }
    }

参考地址:https://github.com/huyuqiwolf/BannerGitHub - huyuqiwolf/Banner