点击上方蓝字关注码个蛋
用它可以大大提高用户交互体验。
作者博客
http://rkhcy.github.io/
源码地址
https://github.com/Rkhcy/TransitionNote2
文章目录
0. 概述
1. Content Transition
1.1. 使用
1.2. 例子
1.3. 具体流程
2. ShareElement Transition
2.1. 例子
2.2. 具体流程
2.3. 延迟加载
0
概述
在「Android 4.4.2引入的超炫动画库」中对于Transition的框架和常用的API使用进行了分析,Transition最常用的是在界面过渡方面,本文继续学习Transition在界面过渡上的使用。在界面过渡上,Transition分为不带共享元素的Content Transition和带共享元素的ShareElement Transition。
1
Content Transition
先看下content transition的一个例子,在Google Play Games上的应用:
在经过学习后我们也可以设计出类似的效果,首先需要了解在界面过渡中涉及到的一些重要方法,从ActivtyA调用startActivity方法唤起ActivityB,到ActivityB按返回键返回ActivityA涉及到与Transition有关的方法
ActivityA.exitTransition()
ActivityB.enterTransition()
ActivityB.returnTransition()
ActivityA.reenterTransition()
因此,只要我们在对应的方法中设置了Transition就可以了。在默认没有设置对应Transition的情况下,Material-theme应用的exitTransition为null,enterTransition为Fade,如果reenterTransition和returnTransition未设定,则分别对应exitTransition和enterTransition。
使用
在style中添加android:windowContentTransitions 属性启用窗口内容转换(Material-theme应用默认为true),指定该Activity的Transition
也可以在代码中指定
然后启动Acticity
例子
这里在代码中指定ActivityA的exitTransition:
使用xml方式指定ActivityB的enterTransition:
运行效果如下:
上图动画有两个问题:
ActivityA的exitTransition还没完全走完ActivityB的enterTransition就执行了,ActivityB的returnTransition还没完全走完ActivityA的reenterTransition就执行了;
状态栏和导航栏的动画不太协调;
问题1是因为默认情况下enter/return transition会比exit/reenter transition完全结束前稍微快一点运行,如果想让前者完全运行完后者再进来,可以在代码中调用Window的
或者在xml中设置
运行如下:
再看下问题2,默认情况下状态栏和标题栏也会参与动画(如果有导航栏也会,测试机默认木有导航栏),当我们把xxxoverlap属性设为false后就看得比较明显了,如果不想让它们参与动画通过excludeTarget()将其排除,在代码中:
或者在xml中:
效果如下:
具体流程
ActivityA startActivity()
确定需要执行exit Transition的target View
Transition的captureStartValues()获取target View Visibility的值(此时为VISIBLE)
将target View Visibility的值设为INVISIBLE
Transition的captureEndValues()获取target View Visibility的值(此时为INVISIBLE)
Transition的createAnimator()根据前后Visibility的属性值变化创建动画
ActivityB Activity 开始
确定需要执行enter Transition的target View
Transition的captureStartValues()获取获取target View Visibility的,初始化为INVISIBLE
将target View Visibility的值设为VISIBLE
Transition的captureEndValues()获取target View Visibility的值(此时为VISIBLE)
Transition的createAnimator()根据前后Visibility的属性值变化创建动画
2
ShareElement Transition
shareElement Transition的例子
shareElement Transition指的是共享元素从activity/fragment到其他activity/fragment时的动画
有了上面的分析看名字应该也猜得出方法对应的功能了,如果没有设置exit/enter shared element transitions,默认为 @android:transition/move,上面的Content Transition是根据Visibility的变化创建动画,而shareElement Transition是根据大小,位置,和外观的变化创建动画,如chanageBounds、changeTransform、ChangeClipBounds、 ChangeImageTransform等,具体API使用和效果可以参考上篇。指定shareElement Transition可以通过代码形式:
也可以通过xml形式:
然后启动Acticity
在布局文件中对于要共享的View添加android:transitionName且保持一致,如果要共享的View有点多,可以通过Pair,Pair
例子
在ActivityB的theme中添加SharedElementEnterTransition
change_image_transform.xml
执行效果:
具体流程
从图上看,好像图片是从一个ActivityA”传递”到另一个ActivityB,实际上真正负责绘制都发生在ActivityB上:
ActivityA调用startActivity()后ActivityB处于透明状态
Transition收集ActivityA中共享View的初识状态,并传递给ActivityB
Transition收集ActivityB中共享View的最终状态
Transition根据状态改变创建动画
Transition隐藏ActivityA,随着ActivityB的共享View运动到指定位置,ActivityB的背景在ActivityA上淡入,并随着动画完成而完全可见。
我们可以通过修改Activity背景淡入淡出时间来验证,在ActivityB中加入
为了更直观,把ActivityA的exitTransition先注释掉,运行效果:
可以看到,ActivityB确实像盖在ActivityA上,这里用到了 ViewOverlay,原理简单来说就是在其他View上draw,共享View利用该技术可以实现画在其他View上。我们可以通过Window的setSharedElementsUseOverlay(false)来关闭该功能,不过这样一来会使最终结果和你预想的不一致,默认该值为true。
延迟加载
上面分析Transition会获取共享视图前后的状态值来创建动画,如果我们的图片是网上下载的,那么很有可能图片的准确大小需要下载下来才能确定,Activity Transitions API提供了一对方法暂时推迟过渡,直到我们确切地知道共享元素已经被适当的渲染和放置。在onCreate中调用postponeEnterTransition()(API >= 21)或者supportPostponeEnterTransition()(API < 21)延迟过渡;当图片的状态确定后,调用startPostponedEnterTransition()(API >= 21)或supportStartPostponedEnterTransition()(API < 21)恢复过渡,常见处理:
Thanks to
Material-Animations
Getting Started with Activity & Fragment Transitions (part 1-4)
What are all these dang Transitions
Shared Element Activity Transition
Define custom animations
Presentation-ContentTransition
码个蛋节后福利(如约而至)