1、概述
谷歌在android3.0时候给我们带来了属性动画,真正意义上带来了”动画“,以前的帧动画也就4中效果的组合(旋转、淡入淡出、放大缩小、平移),而且只是表面的动画,最经典的比如,把一个button按钮移动到另一个位置,然后去点击,一点反应都没有,但是点击原来空白位置仍然有点击事件触发。而属性动画彻彻底底解决这个问题。
属性动画到底带来了哪些属性呢?如下:
(1)Duration:动画持续时间
(2)TimeInterpolation: 用于定义动画变化率的接口,
(3)TypeEvaluator: 用于定义属性值计算方式的接口,系统自带int,float,color类型,
(4)Animationsets:动画集合,可以设置顺序
(5)Frame refreash delay:属性值计算间隔,默认为10ms,(最终刷新时间还受系统进程调度与硬件的影响)
(6)RepeatCountry and behavoir:重复次数与方式
在官方文档谷歌还给我们俩个示意图http://developer.android.com/intl/zh-cn/guide/topics/graphics/prop-animation.html (自备梯子)
都是演示了在40ms内将属性x从0变化到了40,二者使用的插值器不同,图一是线性插值器,图二使用的是AccelerateDecelerateInterpolator,然后谷歌还帮我们还原了图二中
t=10ms是x=6为啥是等于6.
Step1:计算流逝的时间因子
elapsed fraction = 10/40 = 0.25
Step 2:计算插值器
这里使用的是AccelerateDecelerateInterpolator
ok,此时的返回值为 cos(0.25+1)*π/2+0.5 = 0.146466,约等于0.15
Step3: 计算属性值
采用的是整型估值器
然后谷歌直接给我们算此时属性了
x = 0+(40-0)*0.15 = 6,看似很正常,值也对?但是估值器真的可以这么计算么?
在弄清楚这个问题前,我们先来看看插值器和估值器
插值器如何完成速率控制?
估值器凭借什么去估值?
二者之间的联系呢?
2、时间插值器
最终都要实现 TimeInterpolation 因为也叫时间插值器
用于定义动画变化率,
作用:根据时间流逝的百分比计算出当前属性值改变的百分比。
系统已有的插值器:
①LinearInterpolator(线性插值器):匀速动画。
②AccelerateDecelerateInterpolator(加速减速插值器):动画两头慢,中间快。
③DecelerateInterpolator(减速插值器):动画越来越慢
插值器原理:
本质是时间的函数,定义了动画的变化规律(提前/延迟执行默认的时间点来达到加速/减速的效果!)
如何使用:
只需要实现一个方法—>getInterpolation(floatinput)
方法作用:
主要是将消逝的时间因子映射(函数)成插值器的因子
看一个加速插值器(AccelerateInterpolator)的例子源代码如下:
对应的函数图如下
这里我们通过函数改变动画真实执行的时间,比如在0.3时候我们执行的是0.09秒的时间,整体效果是跟函数的斜率有关系的 变化速度∝ 斜率,因此在单位时间内产生了整体的加速效果。
根据不同的函数我们可以设计出千奇百怪的插值,比如
更多插值器函数请参考 http://cogitolearning.co.uk/?p=1078
小结一下插值器:
(1)getInterpolation(floatinput)其实改变的是默认动画的时间点elapsedfraction,提前或者延迟动画时间点来达到加速/减速效果;
(2)只是对动画执行过程中时间因子进行修饰,而不是轨迹
3、估值器
作用:根据当前属性改变的百分比来计算改变后的属性值,最终使用反射机制来改变属性变化
系统已有的估值器:
①IntEvaluator:针对整型属性
②FloatEvaluator:针对浮点型属性
③ArgbEvaluator:针对Color属性
我们可以看到它使用的是泛型,这样可以确保“属性动画可以对任何属性(具有set/get)方法的属性做改变”
在Android系统中支持的属性类型
Int——>IntEvaluator
Float——>IntEvaluator
Color——>ArgbEvaluator
其他类型则需要实现TypeEvaluator接口,操作起来也比较直观,看俩个系统的实例
可以看出基本上按照
4、二者之间的关系
它们是实现非匀速动画的重要手段。属性动画是对属性做动画,属性要实现动画,首先由TimeInterpolator(插值器)根据时间流逝的百分比计算出当前属性值改变的百分比,并且插值器将这个百分比返回,这个时候插值器的工作就完成了。比如插值器返回的值是0.5,很显然我们要的不是0.5,而是当前属性的值,即当前属性变成了什么值,这就需要估值器根据当前属性改变的百分比来计算改变后的属性值,根据这个属性值,我们就可以设置当前属性的值了。
5、思考的问题
TimeInterpolation:
插值器都必须实现的接口,定义了动画的变化率,如线性,非线性,最高接口
TypeEvaluator:
定义了属性值的计算方式,系统有int,float,color类型,根据属性的开始、结束值和插值一起计算出当前时间的属性值,终极方法,整个计算过程的结尾。
TypeEvalutor的evaluate方法接收的fraction究竟来自于哪里? 真的是插值器的getInterpolator返回的参数么????
以ObjectAnimator.ofFloat()为例
动画开始的主要流程是这样的
分析FloatKeyframeSet.java的getFloatValue(float fraction)方法
先从该入口参数float fraction分析开来
在FloatKeyframeSet.java我们可以在getFloatValue(float fraction)中发现这里分4种情况做处理
这里需要注意mKeyframeNums(初始化关键帧),比如
关键帧就是2
举个栗子:
ObjectAnimator.ofFloat(5f,10f)或者ObjectAnimator.ofFloat(10f)这里的关键帧就是2,后面一个帧系统会帮你补全
此时估值器的fraction就是插值器计算的值!
再举个三个关键帧的栗子
现在清楚了吧?!偷了点懒,把自己ppt的东西直接截图了
参考文献
http://www.lightskystreet.com/2014/12/04/propertyview-anim-analysis/