摘要:本文就知乎客户端启动页面为例,教你如何实现视差滚动效果。比如知乎启动页共有个页面,分别是,,,,,初始状态也就是页面静止时,页面的正好是,页面是。不过请注意,其素材均取自于知乎客户端你懂的,学习交流即可,请勿用作商业用途。
前言欢迎转载,但请务必注明出处!http://ryanhoo.github.io/blog/2014/07/16/step-by-step-implement-parallax-animation-for-splash-screen-of-zhihu/
Parallax Scrolling(视差滚动),是一种常见的动画效果。视差一词来源于天文学,但在日常生活中也有它的身影。在疾驰的动车上看风景时,会发现越是离得近的,相对运动速度越快,而远处的山川河流只是缓慢的移动着,这就是最常见的视差效果。视差动画独有的层次感能带来极为逼真的视觉体验,iOS、Android Launcher、Website都将视差动画作为提升用户视觉愉悦度的不二选择。
客户端应用第一次打开出现引导页也不是什么新鲜的事儿,ViewPager配上几张设计师精心绘制的图片,分分钟即可了事。但是总有人把平凡的事情做到不平凡,如本文的知乎客户端,亦或是新浪微博贺岁版,百度贴吧某版等众多应用里都出现了视差动画的身影,随着用户手指的滑动,反馈以灵动、贴近真实的视觉以及操作体验,对应用的初始印象登时被提升到一个极高的点。
给我印象最深的是去年新浪微博的贺岁版,引导页是一系列的年画,里面有红色剪纸的小孩儿,滑动界面的时候感觉这些元素在『动』,是真正的灵动,能勾起人童年的回忆,年味儿十足。不过话说我年怎么过跟新浪微博一毛钱关系都没有,但是这个启动页却是深得我意。只是这个版本的微博找不到了,正好前两天看到知乎的启动页做的也不错,就正好拿来练练手吧。
本文就知乎Android客户端启动页面为例,教你如何实现视差滚动效果。
界面分析细心把玩下知乎的启动页,不难分析出来,视差动画主要体现在背景层渐变、内容层元素差异滚动上,动画内容分别是:
内容:元素差异滚动,形成视差效果(*)
背景:随着界面的滑动,颜色由深蓝色渐变为浅蓝色(*)
文字:底部提示文案会随页面变动而切换,有简单的淡入淡出效果
界面动画:界面打开,元素的出场动画(第一页以及最后一页)
鉴于其它几项比较简单,本文主要讲视差动画以及背景渐变的实现,其它几项请自行参阅代码,见后文。
Parallax Scrolling这里的视差滚动效果,主要表现为内容元素滚动速率的差异上。比如在ViewPager中滑动了1px,而A元素移动2px,B元素移动1.5px,这种移动差距的比率,我称之为parallaxCofficient,即视差系数或者视差速率,正是同一个界面中的元素,由于层级不同,赋予的视差系数不同,在移动速度上的差异形成了视差的错觉,这就是我们要追求的效果。
那知道原理就好办了,使用ViewPager.OnPageChangeListener,动态计算不就得了。no no no! 后面完成背景渐变效果确实需要计算这个,但是ViewPager已经为我们准备好了变形元素transformium: ViewPager.PageTransformer,它有一个抽象方法transformPage(View page, float position),正是为我们完成视差动画量身定制的。
ViewPager.PageTransformerPageTransformer在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 view被NoSaveStateFrameLayout包装,也就是说page.getChildAt(0)即是每个page实际的child view。
Param 2: float positionposition这个参数不看代码或者文档,总会误以为就是我们熟知的integer position,不过它实际上是滑动页面的一个相对比例,本质跟 1、2、3、4 这种position是一样的。
比如知乎启动页共有6个页面,分别是A,B,C,D,E,F初始状态也就是A页面静止时,A页面的position正好是0,B页面是1。而后滑动页面(B -> A),在这个过程中A的position是间于[-1, 0],B页面则是间于[0, 1]。
不过这个参数的文档却是简单不够直观,对照上面的例子,现在应该很清晰了。
ParallaxTransformerPosition 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.
根据上面的分析,我们可以得出一个相对简单的自定义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; } @Override public void transformPage(View page, float position) { float scrollXOffset = page.getWidth() * parallaxCoefficient; // ... // layer is the id collection of views in this page for (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); } @Override public 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); } @Override public void onPageSelected(int position) {} @Override public void onPageScrollStateChanged(int state) {} }源码
代码已经push到Github了,诸位自取。不过请注意,其素材均取自于知乎Android客户端(你懂的),学习交流即可,请勿用作商业用途。
还求更优雅的实现方式,欢迎发起pull request。
Zhihu-Parallax-Animation
参考Using Parallax for Fun and Profit
视差滚动(Parallax Scrolling)效果的原理和实现
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/12125.html
摘要:本文就知乎客户端启动页面为例,教你如何实现视差滚动效果。比如知乎启动页共有个页面,分别是初始状态也就是页面静止时,页面的正好是,页面是。不过请注意,其素材均取自于知乎客户端你懂的,学习交流即可,请勿用作商业用途。 原文地址:http://www.codefrom.com/c/198 前言 Parallax Scrolling (视差滚动),是一种常见的动画效果。视差一词来源...
摘要:它的子控件使用属性可以实现向上滑动隐藏控件的功能。滚动事件由可滚动控件设置属性通知。属性值介绍包裹的子控件使用表示该可以被滑出屏幕。表示任意向下的滚动都会导致该变为可见,启用快速返回模式。通过的子视图的属性控制。 2. TextInputLayout 2.0 环境配置 需要引用Support v7 和 Support Design 包 You need to use a...
摘要:可以感受下种不同取值的不同效果使用实现滚动视差首先,我们使用来实现滚动视差。何为滚动视差 视差滚动(Parallax Scrolling)是指让多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。 作为网页设计的热点趋势,越来越多的网站应用了这项技术。 通常而言,滚动视差在前端需要辅助 Javascript 才能实现。当然,其实 CSS 在实现滚动视差效果方面,也有着不俗...
摘要:通常而言,滚动视差在前端需要辅助才能实现。当然,其实在实现滚动视差效果方面,也有着不俗的能力。此关键字表示背景相对于视口固定。使用实现滚动视差言归正传,下面介绍另外一种使用实现的滚动视差效果,利用的是。 何为滚动视差 视差滚动(Parallax Scrolling)是指让多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。 作为网页设计的热点趋势,越来越多的网站应...
摘要:近些年讨论得很热烈的设计趋势是视觉差滚动效果。在本教程中,我会介绍视觉差滚动和用插件来制作视觉差滚动效果。如果你想使用,可以通过以下命令下载好后,在页面中引用完成后,开始给页面添加视觉差滚动效果。在一个页面运用创建一个视差滚动效果的示例。 近些年讨论得很热烈的设计趋势是视觉差滚动效果。不管你喜不喜欢,很多网站都在用它。在本教程中,我会介绍视觉差滚动和用jQuery插件Stellar.j...
阅读 1880·2023-04-26 00:00
阅读 2710·2021-09-24 10:37
阅读 3272·2021-09-07 09:58
阅读 1304·2019-08-30 15:56
阅读 2084·2019-08-30 13:11
阅读 2111·2019-08-29 16:38
阅读 777·2019-08-29 12:58
阅读 1701·2019-08-27 10:54