欢迎转载,但请务必注明出处!http://ryanhoo.github.io/blog/2014/07/16/step-by-step-implement-parallax-animation-for-splash-screen-of-zhihu/

前言

Parallax Scrolling(视差滚动),是一种常见的动画效果。视差一词来源于天文学,但在日常生活中也有它的身影。在疾驰的动车上看风景时,会发现越是离得近的,相对运动速度越快,而远处的山川河流只是缓慢的移动着,这就是最常见的视差效果。视差动画独有的层次感能带来极为逼真的视觉体验,iOSAndroid LauncherWebsite都将视差动画作为提升用户视觉愉悦度的不二选择。

客户端应用第一次打开出现引导页也不是什么新鲜的事儿,ViewPager配上几张设计师精心绘制的图片,分分钟即可了事。但是总有人把平凡的事情做到不平凡,如本文的知乎客户端,亦或是新浪微博贺岁版,百度贴吧某版等众多应用里都出现了视差动画的身影,随着用户手指的滑动,反馈以灵动、贴近真实的视觉以及操作体验,对应用的初始印象登时被提升到一个极高的点。

给我印象最深的是去年新浪微博的贺岁版,引导页是一系列的年画,里面有红色剪纸的小孩儿,滑动界面的时候感觉这些元素在『动』,是真正的灵动,能勾起人童年的回忆,年味儿十足。不过话说我年怎么过跟新浪微博一毛钱关系都没有,但是这个启动页却是深得我意。只是这个版本的微博找不到了,正好前两天看到知乎的启动页做的也不错,就正好拿来练练手吧。

本文就知乎Android客户端启动页面为例,教你如何实现视差滚动效果。

界面分析

细心把玩下知乎的启动页,不难分析出来,视差动画主要体现在背景层渐变、内容层元素差异滚动上,动画内容分别是:

  • 内容:元素差异滚动,形成视差效果(*)
  • 背景:随着界面的滑动,颜色由深蓝色渐变为浅蓝色(*)
  • 文字:底部提示文案会随页面变动而切换,有简单的淡入淡出效果
  • 界面动画:界面打开,元素的出场动画(第一页以及最后一页)

鉴于其它几项比较简单,本文主要讲视差动画以及背景渐变的实现,其它几项请自行参阅代码,见后文。

Parallax Scrolling

这里的视差滚动效果,主要表现为内容元素滚动速率的差异上。比如在ViewPager中滑动了1px,而A元素移动2pxB元素移动1.5px,这种移动差距的比率,我称之为parallaxCofficient,即视差系数或者视差速率,正是同一个界面中的元素,由于层级不同,赋予的视差系数不同,在移动速度上的差异形成了视差的错觉,这就是我们要追求的效果。

那知道原理就好办了,使用ViewPager.OnPageChangeListener,动态计算不就得了。no no no! 后面完成背景渐变效果确实需要计算这个,但是ViewPager已经为我们准备好了变形元素transformium: ViewPager.PageTransformer,它有一个抽象方法transformPage(View page, float position),正是为我们完成视差动画量身定制的。

ViewPager.PageTransformer

PageTransformer在ViewPager滑动时被触发,它为我们自定义页面中进行视图变换打开了一扇大门。

public abstract void transformPage (View page, float position)

ViewPager源码中,我们可以很直观的看到它的调用过程:


// ViewPager#onPageScrolled
if (mPageTransformer != null) {final int scrollX = getScrollX();final int childCount = getChildCount();for (int i = 0; i < childCount; i++) {final View child = getChildAt(i);final LayoutParams lp = (LayoutParams) child.getLayoutParams();if (lp.isDecor) continue;final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();mPageTransformer.transformPage(child, transformPos);}
}

Param 1: View page

从上面的代码中,不难看出,page就是当前被滑动的页面,调试得知,每一个child viewNoSaveStateFrameLayout包装,也就是说page.getChildAt(0)即是每个page实际的child view

Param 2: float position

position这个参数不看代码或者文档,总会误以为就是我们熟知的integer position,不过它实际上是滑动页面的一个相对比例,本质跟 1、2、3、4 这种position是一样的。

比如知乎启动页共有6个页面,分别是ABCDEF初始状态也就是A页面静止时,A页面的position正好是0B页面是1。而后滑动页面(B -> A),在这个过程中Aposition是间于[-1, 0]B页面则是间于[0, 1]

不过这个参数的文档却是简单不够直观,对照上面的例子,现在应该很清晰了。

Position of page relative to the current front-and-center position of the pager. 0 is front and center. 1 is one full page position to the right, and -1 is one page position to the left.

ParallaxTransformer

根据上面的分析,我们可以得出一个相对简单的自定义transformer,对page view进行遍历,递增或者递减其parallaxCofficient,以得到我们预期的效果,具体的系数设置请参考代码。

class ParallaxTransformer implements ViewPager.PageTransformer {float parallaxCoefficient;float distanceCoefficient;public ParallaxTransformer(float parallaxCoefficient, float distanceCoefficient) {this.parallaxCoefficient = parallaxCoefficient;this.distanceCoefficient = distanceCoefficient;}@Overridepublic void transformPage(View page, float position) {float scrollXOffset = page.getWidth() * parallaxCoefficient;// ...// layer is the id collection of views in this pagefor (int id : layer) {View view = page.findViewById(id);if (view != null) {view.setTranslationX(scrollXOffset * position);}scrollXOffset *= distanceCoefficient;}}
}

背景渐变

留心才会发现,从第一页滑动到最后一页,背景色会平滑的从深蓝色过度到浅蓝色,这种效果又该怎么实现呢?

用过Property Animation的同学应该知道,以前的Animation只能用在View上,而Property Animation却可以用在任意类型属性值上,这归功于TypeEvaluator

正好我们有ArgbEvaluator,它可以估算两个颜色值之间,任意部分的色值。因此,只需要指定起始色值以及最终的色值,传入滑动所对应的fraction即当前位置相对总距离的比例值,即可获得相应的色值。

public class ArgbEvaluator implements TypeEvaluator {public Object evaluate(float fraction, Object startValue, Object endValue) {// ...}
}

当然,前面说到需要使用ViewPager.OnPageChangeListener的:

class GuidePageChangeListener implements ViewPager.OnPageChangeListener {ArgbEvaluator mColorEvaluator;int mPageWidth, mTotalScrollWidth;int mGuideStartBackgroundColor, mGuideEndBackgroundColor;public GuidePageChangeListener() {mColorEvaluator = new ArgbEvaluator();mPageWidth = getWindowManager().getDefaultDisplay().getWidth();mTotalScrollWidth = mPageWidth * mAdapter.getCount();mGuideStartBackgroundColor = getResources().getColor(R.color.guide_start_background);mGuideEndBackgroundColor = getResources().getColor(R.color.guide_end_background);}@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {float ratio = (mPageWidth * position + positionOffsetPixels) / (float) mTotalScrollWidth;Integer color = (Integer) mColorEvaluator.evaluate(ratio, mGuideStartBackgroundColor, mGuideEndBackgroundColor);mPager.setBackgroundColor(color);}@Overridepublic void onPageSelected(int position) {}@Overridepublic void onPageScrollStateChanged(int state) {}
}

源码

代码已经pushGithub了,诸位自取。不过请注意,其素材均取自于知乎Android客户端(你懂的),学习交流即可,请勿用作商业用途。

还求更优雅的实现方式,欢迎发起pull request

Zhihu-Parallax-Animation

参考

  1. Using Parallax for Fun and Profit
  2. 视差滚动(Parallax Scrolling)效果的原理和实现

转载于:https://my.oschina.net/ryanhoo/blog/292574

【Parallax Animation】实现知乎 Android 客户端启动页视差滚动效果相关推荐

  1. android 开机动画 渐变,[Parallax Animation]实现知乎 Android 客户端启动页视差滚动效果...

    前言 Parallax Scrolling (视差滚动),是一种常见的动画效果.视差一词来源于天文学,但在日常生活中也有它的身影.在疾驰的动车上看风景时,会发现越是离得近的,相对运动速度越快,而远处的 ...

  2. 实现知乎 Android 客户端启动页视差滚动效果

    http://ryanhoo.github.io/blog/2014/07/16/step-by-step-implement-parallax-animation-for-splash-screen ...

  3. android动画知乎,GitHub - ryanhoo/Zhihu-Parallax-Animation: 知乎 Android 客户端启动页的视差动画效果实现...

    Parallax Animation 知乎 Android 客户端启动页的视差动画效果实现 Blog Declaration 项目中图片等素材均取自于知乎 Android 客户端,仅作学习交流之用,请 ...

  4. appium 自动化测试之知乎Android客户端

    appium是一个开源框架,相对来说还不算很稳定.转载请注明出处!!!! 前些日子,配置好了appium测试环境,至于环境怎么搭建,参考:http://www.cnblogs.com/tobecraz ...

  5. android 测试机 知乎,appium 自动化测试之知乎Android客户端

    appium是一个开源框架,相对来说还不算很稳定.转载请注明出处!!!! 接下来我们研究一下测试知乎Android客户端.自行下载 配置目录如下:把知乎客户端命名为zhihu.apk 编写基于java ...

  6. Qt for Android 自定义启动页(解决启动页拉伸的问题)

    前言 在之前的文章中(Qt for Android Splash启动页最简单延时关闭)介绍了如何在 Qt 开发的 android 应用中添加启动页,那里介绍的方法是直接给启动页设置一张图片来显示,但是 ...

  7. android打开app白色页面,完美解决Android App启动页有白屏闪过的问题

    应用启动的时候有短暂的白屏,如图: 可以通过设置theme的方式来解决 @color/colorPrimary @color/colorPrimaryDark @color/colorAccent t ...

  8. android动画知乎,Android模仿知乎的回答详情页的动画效果

    废话不多说,咱们第一篇文章就是模仿"知乎"的回答详情页的动画效果,先上个原版的效果图,咱们就是要做出这个效果 在实现之前,我们先根据上面的动画效果,研究下需求,因为gif帧数有限, ...

  9. Android app启动页广告

    一款app刚出世的时候是没有广告的,流畅的速度和粘性的设计,让这款app使用的人越来越多,这个时候,广告就诞生了,app中加入广告的位置有很多,最常见的就是启动页的广告,首页的banner的轮询广告, ...

最新文章

  1. GitHub标星1.2w+,Chrome最天秀的插件都在这里
  2. 微服务领域,为什么选SpringCloud而不是Dubbo?
  3. AI女神李飞飞:成为顶尖科学家的人生路
  4. 计算机三级网络技术题库第15套,计算机等级考试理论试题第二十五套
  5. WEB框架原理(socket)
  6. Linux系统中ctrl+c、 ctrl+z、 ctrl+\ 产生的信号名称
  7. RDMA技术详解(二):RDMA Send Receive操作
  8. 基于PHP的CURL快速入门
  9. 国科大生命科学学院华大专项-孙海汐导师课题组专访:去伪存真的过程一定不是一帆风顺的...
  10. python 动态类型_动态类型(Dynamic type)
  11. 卢松松分享独立博客运营推广经验
  12. 90 矩阵——矩阵微分与求导
  13. 0 最优化问题数学概念补充
  14. IDEA如何安装使用阿里代码规范插件
  15. 基于SVM算法的人脸微笑识别
  16. 数据分析统计学基础笔记
  17. 【软考-软件设计师】(五).计算机网络
  18. php卡片式,50+创意卡片式网站欣赏
  19. 浙江省计算机三级网络及安全技术资料(最后有我考完后的想法)
  20. 偷懒是程序员的一种至高境界

热门文章

  1. java string 序列化_详解JAVA序列化
  2. provisional headers are shown报错的解决方案
  3. 计算机茶包装设计论文,创意设计论文茶叶包装设计论文
  4. 梯形时间同步--直接规划法
  5. 专业游戏后端引擎“坚果矩阵” 解初创游戏工作室的燃眉之急
  6. 三星相机数据恢复,数码相机照片删除怎么恢复
  7. 【分享汇总】25个主题分享,360°领略OpenHarmony最新技术版图
  8. 月薪过万的文案,都在用这9个网站(速看+收藏)
  9. 查看电脑软件安装路径
  10. CMOS放电 CMOS放电的作用 CMOS放电的方法