Android使用ViewPager2实现画廊效果的技术点

2,859 阅读1分钟

实现画廊效果首先我们要考虑的是,如何让ViewPager2同时显示多个页面Item。也就是一起显示前后的两个item

思路:给ViewPager2左边和右边设置一个margin、固定ViewPager大小或者根据想要显示的Item个数动态计算ViewPager的大小,然后设置clipChildren=false,允许ViewPager中看不到的界面绘制出来。

clipChildren:我们知道,在Android中,布局中的控件超出父布局的大小部分不会被绘制,但是当clipChildren设置为false时,子View的内容可以超出父布局被绘制出来。

image.png

设置效果如上

其次,我们需要设置每个页面Item的间距,ViewPager2和ViewPager不同,ViewPager使用setPageMargin,但是因为ViewPager2内部是RecyclerView,有类似addItemDecoration的功能,我们添加自带的MarginPageTransformer

然后我们还要为ViewPager2添加一个画廊缩放的效果,ViewPager2的页面切换效果是通过PageTransformer实现的

class ZoomOutPageTransformer : ViewPager2.PageTransformer {

    companion object {
        //自由控制缩放比例
        private const val MIN_SCALE_Y = 0.8f //0.85f
    }

    override fun transformPage(page: View, position: Float) {
        if (position >= 1 || position <= -1) {
            page.scaleY = MIN_SCALE_Y
        } else if (position < 0) {
            //  -1 < position < 0
            //View 在再从中间往左边移动,或者从左边往中间移动
            val scaleY = MIN_SCALE_Y + (1 + position) * (1 - MIN_SCALE_Y)
            page.scaleY = scaleY
        } else {
            // 0 <= positin < 1
            //View 在从中间往右边移动 或者从右边往中间移动
            val scaleY = (1 - MIN_SCALE_Y) * (1 - position) + MIN_SCALE_Y
            page.scaleY = scaleY
        }
    }
}

目前我们已经为ViewPager2设置过一个PageTransformer了,ViewPager2为我们提供了CompositePageTransformer,可以同时设置多个PageTransformer如下:

viewPager.setPageTransformer(CompositePageTransformer().apply {
    addTransformer(ZoomOutPageTransformer())
    addTransformer(MarginPageTransformer(16f.dp(context)))
})

因为我们设置了ViewPager的宽度是没有填满根布局的,所以边缘部分并不能滑动。可以将根布局的Touch事件直接传递给ViewPager中的RecyclerView

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        return mViewPager.getChildAt(0).onTouchEvent(event)
    }

到这,达到了我们期望的效果