####蘑菇街欢迎页
####高仿效果
这里这里…Demo下载地址
#####效果拆解
首先可以把整体效果拆分为静态,动态2部分。
- 静态:1个支持4个页面的ViewPager,每个页面的展示相对固定,不会根据offset进行改变。
- 第1-4页的顶部文案
- 第4页的开始按钮
- 动态:摆放在viewPager上会变形的自定义View,根据offset动态调整需要绘制的元素的宽高,left,top,透明度等。
- 第1页->第2页
- 0%->50%,矩形背景高度增加,先上移,再下移
- 0%->50%,模特图,文案,下移,渐变消失
- 50%-100%,左右裂变出2张背景图,并左右移开
- 50%->100%,第2页,顶部,底部图,渐变显示
- 50%->100%,第2页,3张模特图逐步放大显示
- 0%->100%,底部背景图跟随向左偏移,并消失
- 第2页->第3页
- 0%->50%,矩形背景宽度减少,上移
- 0%->50%,顶部,底部图,3张模特图渐变消失
- 0%->50%,2张裂变背景图跟随向左偏移,并消失
- 50%->100%,第3页,6张模特图逐步放大,渐变显示
- 第3页->第4页
- 0%->50%,矩形背景宽度,高度减少,并逆时针进行旋转
- 0%->50%,6张模特图缩小,渐变消失
- 50%->100%,左右裂变出2张背景图,并左右移开
- 50%->100%,顶部模特,文案,渐变显示
- 50%->100%,底部3长模特图逐步放大,渐变显示
- 第1页->第2页
以上是对部分实现细节的分析,抽取;本文demo会全部实现以上变化效果。
#####实现步骤
1.实现静态的ViewPager 2.根据offset实现矩形背景变化 3.根据offset实现第1页底部背景,第2,4页裂变背景图变化 4.根据offset实现页面切换时,每个页面图片元素的隐藏,显示,变形等效果
- 实现静态的ViewPager
自定义ViewPager,每个页面是一个独立layout,可以自由实现每个页面的顶部文案,和第4个页面的Button
1 |
|
1 |
|
第一步完成,实现代码还是比较简单的,直接看效果:
- 根据offset实现矩形背景变化
自定义会变形的TransforView,在xml布局中摆放在ViewPager之上
1 |
|
给ViewPager添加addOnPageChangeListener()监听,在onPageScrolled()的时候将position,positionOffset,positionOffsetPixels传递给TransforView。
1 |
|
在TransforView中,首先定义页面切换时变化的参数,比如第1页->第2页切换时,第1页的矩形背景高度放大40%,上移30dp,下移60dp,则只需要定义FIRST_HEIGHT=0.4,FIRST_TOP1=-30dp,FIRST_TOP2 =60dp三个参数即可。
1 |
|
TransforView的transfor()方法负责接收position,positionOffset, positionOffsetPixels,并根据position判断当前第几页,从而决定要实现哪些效果。比如在第1页->第2页的0%-50区间时,需要将高度放大40%:mRectBgCurrentHeight =(int) (mPage1RectBgDefaultHeight * (1 + FIRST_HEIGHT * positionOffset * (1 / FIRST_RATE)))。mRectBgCurrentHeight是矩形背景当前的高度,是个动态值,mPage1RectBgDefaultHeight是屏幕处于第1页时矩形背景的初始值,只要基于这个初始值,根据positionOffset计算偏移的比例,就可以知道当前动态的高度值应该是多少。
1 |
|
最后在onDraw方法中,调用canvas.drawRoundRect()将计算好宽,高,left,top的圆角矩形在绘制在canvas上即可。
1 |
|
第2步:通过ViewPager的偏移offset,实现了矩形背景在页面间切换时的变化效果,如下:
- 根据offset实现第1页底部背景,第2,4页裂变图背景图变化
在TransforView的init()初始化方法中,获取并设置图片的默认宽,高,left,top。这里封装了1个ViewModel,里面记录了在canvas上绘制图形需要的bitmap,paint,matrix,width,height,left,top等属性。在调用ViewModel.create()的时候,通过matrix.postScale()将Bitmap缩放一定比例,以便在矩形背景上进行精确的绘制,比如:矩形背景的200,要在1排展示3张图,则每张图的宽度=(200-矩形左边距-矩形右边距-中间2张图的左右边距)/3。
1 |
|
在transfor()中修改图片left,top,实现移动;第1页的底部背景图,根据viewPager向左滑动的距离,跟随左移,直到消失不可见。在第1页滑动到50%时,显示第2页裂变背景图,根据offset分别左右平移,第4页裂变图原理一致,只是绘制前需要通过Matrix.postRotate()将图进行旋转。
1 |
|
效果如下:
- 4个页面切换时,实现每个页面图片元素的隐藏,显示,变形等效果
在transfor()中,根据position判断当前页数,才知道当前是从第几页滑动到第几页,该隐藏,或显示哪些view。
1 |
|
第1页->第2页,偏移区间0%-50%时
- 矩形背景,高度放大40%,向上移动30dp
- 渐渐隐藏第1页顶部,底部图;透明度渐变消失,偏移到50%时完全消失
1 |
|
1 |
|
第1页->第2页,偏移区间50%-100%时
- 矩形背景,向下移动60dp
- 显示第2页裂变背景图,并左右平移
- 逐渐显示第2页,顶部,底部图,3张模特图
1 |
|
1 |
|
第2页->第3页,偏移区间0%-100%时
- 矩形背景,宽度缩小15%
- 矩形背景,上移20dp
1 |
|
第2页->第3页,偏移区间0%-50%时
- 裂变背景图跟随滑动,向左偏移至消失
- 渐渐减少透明度,隐藏第2页的顶部图,3张模特图,底部图
1 |
|
第2页->第3页,偏移区间50%-100%时
- 依次显示第3页,6张模特图
1 |
|
第3页->第4页,偏移区间0%-100%时
- 矩形背景,宽度缩小10%
- 矩形背景,高度缩小10%
- 矩形背景,逆时针旋转10度
1 |
|
第3页->第4页,偏移区间0%-50%时
- 渐渐缩放,隐藏6张模特图
1 |
|
第3页->第4页,偏移区间50%-100%时
- 渐渐显示顶部图,底部3张模特图
- 显示第4页裂变背景图,并左右平移
1 |
|
最后在onDraw(),将计算好偏移值的view都绘制出来。
1 |
|
最终效果:
目前还有一些细节的效果,以及适配,性能调优还没实现。虽然原理不难,不过要真正完整的实现以上效果,也算呕心沥血吧!难点就在于如何精细化的控制每个view的属性,因为页面中每个图片的位置,大小都是在参照其他view的基础上进行计算后得出的。现在市场上很多APP的欢迎页都有类似比较动态的效果,原理就是ViewPager+Canvas绘制,掌握了本文的demo,其他实现原理应该是一样样的。感兴趣的朋友可以Github上下载源码查看, 注释还算清晰,有什么问题页欢迎提出,如果本文稍微对您有点启示的话还请点个“喜欢”,谢谢了