如何利用RecyclerView打造炫酷滑动卡片

效果:
没错,就是上面这玩意儿,是不是很炫酷,本着发扬一名码农的职业精神,我心里便痒痒的想实现这种效果,当然因为长期的fork,第一时间我还是上网搜了搜,有木有哪位好心人已经开源了类似的控件 。借助强大的,我马上搜到了一个项目,是仿照探探的老父亲的app动画效果打造的,果然程序员都一个操行,看到好看的就想动手实现,不过人家的成绩让我可望而不可及~
他实现的效果是这样的:
嗯,还不错,为了进行思想上的碰撞,我就了一下他的源码,稍稍read了一下~_~
作为一个有思想,有抱负的程序员,怎么能满足于别人的库呢?必须得自己动手,丰衣足食啊!
正式开工 思考
一般这种View都是自定义的,然后重写,但是有木有更简单的方法呢?由于项目里一直使用,那么能不能用来实现这种效果呢?能,当然能啊!得力于优雅的扩展性,我们完全可以自定义一个来实现嘛 。
布局实现
可以通过自定义来实现各种布局,官方自己提供了、,相比于,可谓是方便了不少 。同样,我们也可以通过自定义,实现这种View一层层叠加的效果 。
自定义,最重要的是要重写()
【如何利用RecyclerView打造炫酷滑动卡片】@Overridepublic void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {detachAndScrapAttachedViews(recycler);for (int i = 0; i < getItemCount(); i++) {View child = recycler.getViewForPosition(i);measureChildWithMargins(child, 0, 0);addView(child);int width = getDecoratedMeasuredWidth(child);int height = getDecoratedMeasuredHeight(child);layoutDecorated(child, 0, 0, width, height);if (i < getItemCount() - 1) {child.setScaleX(0.8f);child.setScaleY(0.8f);}}}
这种布局实现起来其实相当简单,因为每个child的left和top都一样,直接设置为0就可以了,这样child就依次叠加在一起了,至于最后两句,主要是为了使顶部Child之下的有一种缩放的效果 。
动画实现
下面到了最重 要的地方 了,主要分为以下几个部分 。
(1)手势追踪
当手指按 下时,我们 需要取到iew的顶部Child,并让其跟随手指滑动 。
public boolean onTouchEvent(MotionEvent e) {if (getChildCount() == 0) {return super.onTouchEvent(e);}View topView = getChildAt(getChildCount() - 1);float touchX = e.getX();float touchY = e.getY();switch (e.getAction()) {case MotionEvent.ACTION_DOWN:mTopViewX = topView.getX();mTopViewY = topView.getY();mTouchDownX = touchX;mTouchDownY = touchY;break;case MotionEvent.ACTION_MOVE:float dx = touchX - mTouchDownX;float dy = touchY - mTouchDownY;topView.setX(mTopViewX + dx);topView.setY(mTopViewY + dy);updateNextItem(Math.abs(topView.getX() - mTopViewX) * 0.2 / mBorder + 0.8);break;case MotionEvent.ACTION_UP:mTouchDownX = 0;mTouchDownY = 0;touchUp(topView);break;}return super.onTouchEvent(e);}
手指按下的时候,记录tw的位置,移动的时候,根据偏移量,动态调整的位置,就实 现了基本效果 。但是这样还不够,记得我们在实现布局时,对其他子View进行了缩放吗?那时候的缩放是为 现在做准备的 。当手指在屏幕上滑动时,我们同样会 调用(),对top 下面的子view进行缩放 。
private void updateNextItem(double factor) {if (getChildCount() < 2) {return;}if (factor > 1) {factor = 1;}View nextView = getChildAt(getChildCount() - 2);nextView.setScaleX((float) factor);nextView.setScaleY((float) factor);}
这里的计算很简单,只要当dView滑动到设置 的边界时,nextV iew刚好缩放到原本大小,即=1,就可以了 。因为一开始缩放为0.8,所以可计算出: