背景
最近在学习英语,在使用英语流利说App的时候看到一个广告banner,如下图:
怎么实现这种效果呢?用ViewPager实现!
实现
从图中可以看出,一次显示三个Item,一个完整的,两个冒点头并且相较于完整的高度较小,我们知道平时VIewPager是每个Item占一整页的,怎么实现一页显示三个呢?从ViewPager的onMeasure()与onLayout()我们知道Item的宽高和布局受到ViewPager的Padding影响。相关代码如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
....
// Children are just made to fill our space.
int childWidthSize = measuredWidth - getPaddingLeft() - getPaddingRight();
int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
......
for (int i = 0; i < size; ++i) {
......
int widthSize = childWidthSize;
int heightSize = childHeightSize;
...
final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
child.measure(widthSpec, heightSpec);
}
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
.....
for (int i = 0; i < count; i++) {
int childLeft = 0;
...
childLeft = paddingLeft;
...
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(),
childTop + child.getMeasuredHeight());
}
}
Ok,我们给ViewPager添加padding,看看效果:
emm,Item的大小确实变小了,但是说好的显示三个呢???我们滑动一下看看是啥样子
发现两个Item是相连的,但是只显示一个出来,这是为什么呢?这里涉及到ViewGroup的一个属性clipTopadding,它做了什么呢,看看代码
ViewGroup.class
protected void dispatchDraw(Canvas canvas) {
...
final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
if (clipToPadding) {
clipSaveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,
mScrollX + mRight - mLeft - mPaddingRight,
mScrollY + mBottom - mTop - mPaddingBottom);
}
....
}
文字太过苍白,看图,它的作用大致如下
就是clipToPadding=true时,ViewGroup在绘制子View的时候裁剪了下,OK,现在我们把clipToPadding设为false,效果如下
这下都显示出来了吧,接下来我们给ViewPager设置一个PagerMargin,设置为padding的一半,看看效果
有点那个样子了啊,接下来就是设置pager转变过程中的动画了,就是VIewPager的setPageTransformer()方法,这里有个参数position,它的值反映了pager的转换过程,0代表了pager位于中间的显示位置,-1是在左侧,1在右侧,我们可以通过这个值来写一个动画,这里动画我设置了个简单的,就是改变pager的ScaleY的值,positon为0,scaleY=1,position=-1或position=1,scaleY=0.95,二次方程,求得,y=-xx0.05+1,代码设置如下
vp_gallery.setPageTransformer(false){
page, position ->
page.scaleY=-position*position*0.05f+1f
}
效果如下
基本就是这个亚子了,项目地址