RecyclerView + PagerSnapHelper 实现 抖音 首页翻页的Viewpager效果

610 阅读1分钟

前言

SnapHelper是RecycleView的辅助类,可用来控制在滑动结束后,item的对齐方式。
SnapHelper是一个抽象类,系统内置了两个默认实现。
1.LinearSnapHelper:使当前item居中显示,常用场景是横向的RecyclerView,类似ViewPager效果,但是可以快速滑动(滑动多页)。
2.PagerSnapHelper:展示效果和LinearSnapHelper是一样的,只是限制一次只能滑动一页,不能快速滑动。

1.ac代码

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private var mDataList:ArrayList<String> = ArrayList()
    private lateinit var mMyadapter:PagerSnapHelperAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        for(i in 0 until 100){
            mDataList.add("item$i")
        }
        initUI();
    }

    fun initUI(){
        binding.recyclerviewVertical.isNestedScrollingEnabled=false
        var snapHelper:PagerSnapHelper=object : PagerSnapHelper() {

            override fun findTargetSnapPosition(
                layoutManager: RecyclerView.LayoutManager?,
                velocityX: Int,
                velocityY: Int
            ): Int {
                var targetPos:Int=super.findTargetSnapPosition(layoutManager, velocityX, velocityY)
                Toast.makeText(this@MainActivity,"滑动到$targetPos",Toast.LENGTH_SHORT).show()
                return targetPos
            }

            override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {
                return super.findSnapView(layoutManager)
            }
        }
        snapHelper.attachToRecyclerView(binding.recyclerviewVertical)
        var linearLayoutManager= LinearLayoutManager(this)
        linearLayoutManager.orientation=LinearLayoutManager.VERTICAL
        binding.recyclerviewVertical.layoutManager=linearLayoutManager
        binding.recyclerviewVertical.viewTreeObserver.addOnGlobalLayoutListener(object :ViewTreeObserver.OnGlobalLayoutListener{
            override fun onGlobalLayout() {
                if (Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                    binding.recyclerviewVertical.viewTreeObserver.removeGlobalOnLayoutListener(this)
                }else{
                    binding.recyclerviewVertical.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
                mMyadapter=PagerSnapHelperAdapter(mDataList,binding.recyclerviewVertical.width,binding.recyclerviewVertical.height)
                binding.recyclerviewVertical.adapter=mMyadapter
            }
        })
    }
}

2.相关布局代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview_vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_centerInParent="true"
        android:id="@+id/add_btn"
        android:gravity="center"
        android:layout_width="40dp"
        android:layout_height="40dp"/>
</RelativeLayout>

3.适配器代码

class PagerSnapHelperAdapter:RecyclerView.Adapter<PagerSnapHelperAdapter.ViewHolder> {
    private var mDataList:ArrayList<String> = ArrayList()
    private var mWidth:Int=0
    private var mHeight:Int=0

    constructor(dataset:ArrayList<String>,width:Int,height:Int){
        mDataList=dataset
        mWidth=width
        mHeight=height
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewHolder {
        var view: View = View.inflate(parent.context, R.layout.item_layout, null)
        var contentView: View = view.findViewById(R.id.add_btn)
        var rl: RelativeLayout.LayoutParams =
            contentView.layoutParams as RelativeLayout.LayoutParams
        rl.width = mWidth
        rl.height = mHeight
        contentView.layoutParams = rl
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.itemView.tag=position
        holder.mTextView.text="$position item"
    }

    override fun getItemCount(): Int =mDataList.size

    class ViewHolder(itemView:View): RecyclerView.ViewHolder(itemView) {
        var mTextView:TextView = itemView.findViewById(R.id.add_btn)
    }
}