这次来实现RecyclerView
视差动画,先来看下效果:
那要怎么实现呢?我这里是通过ImageView
设置Matrix
实现,有更好的办法欢迎留言告知。
那么Matrix
是什么呢?我这里就简单的说一下,如果想详细了解的话,请自行搜索查看。
matrix
是一个3*3
的矩阵,MSCALE_X
、MSCALE_Y
是来控制绽放的,MSKEW_X
,MSKEY_Y
是来控制错切的,MTRANS_X
、MTRANS_Y
是来控制位移的,MPERSP_0
、MPERSP_1
、MPERSP_2
是来控制透视的,MSCALE_X
、MSCALE_Y
、MSKEW_X
、MSKEW_Y
是用来控制旋转的。
那我们要怎么对矩阵操作,可能大家都把线性代数还回给老师了,就算没还,算起来也麻烦,所以谷歌给我们提供了方便的方法,分别是preRotate()
、setRotate()
、postRotate
,代表的是左乘、设置和后乘。这之间的差别我就不详细介绍了。视差效果主要用到了位移和缩放。
那这个效果的思路是怎样?我们对效果进行拆分,其实发现每个图片的效果都是一样的,滚动后图片也跟着移动,图片从RecyclerView
顶部到达RecyclerView
底部刚好遍历一整张图片,顶部时,图片也显示顶部。到达底部时,图片也显示底部,如图所示。
那我们可以先对这个效果进行分解,在没有RecyclerView
的时候,对ImageView
进行图片的缩放和移动。
首先为ImageView
设置图片,然后设置ScapeType
为Matrix
,然后根据图片比例进行计算,缩放使图片占满ImageView
,因为我们的图片是要上下移动,所在我们在放大的时候要在CenterCrop
的基础上保证上下有一部分剩余,这样才可以移动。并且图片一开始位于ImageView
的顶部。代码如图所示:
这里做的事件也很简单,获取drawable
的原始宽高和ImageView
的原始宽高,通过postScale()
进行比较缩放,让图片占满整个ImageView
,这里ImageView
的高度乘以1.1主要用于控制缩放后的图片高度超过ImageView
高度的1.1倍。当置于recyclerview
移动时,让任何规格的图片都可以上下移动,产生较明显的视差效果。不然的话当图片控件宽高比相同(小于大于和控件图片比例有关)之类的情况下,会让图片上下无法移动。
那我们怎样对内部的图片进行移动?可以通过postTranslationY()
方法对图片进行上下移动。看,是不是很简单。
通过以上的步骤我们已经可以控制图片缩放到正确比例并上下移动,但是我们可以发现存在一个问题,图片会被移出ImageView
外面。我们可以进行纠正,当图片被移动到ImageView
边框外后,把图片纠正回ImageView
内部。代码如下:
这里主要通过mapRect()
方法获得通过变换后的图片边框位置,然后判断是否超出ImageView
的上下边框,进行纠正,这样就可能防止图片移出ImageView
的边框。
现在我们已经知道怎么图片怎么通过Matrix
进行移动。那实现RecyclerView
的视差动画肯定也难不倒聪明的你,只需要为RecyclerView
添加addOnScrollListener()
监听,当RecyclerView
滚动时,根据每个Item
距离RecyclerView
顶部的距离移动对应的比例。这样,我们就实现了我们的视差效果。