测试安卓动画插入器
六种插入器介绍:
<I>android.view.animation.Interpolator
interpolator
[in'tə:pəuleitə] 跟读 口语练习
n. 窜改者,插入器;内插程序
<C>android.view.animation.AccelerateInterpolator
accelerate
英 [ək'seləreɪt] 美 [ək'sɛləret] 全球发音 跟读 口语练习
vt. 使……加快;使……增速
vi. 加速;促进;增加
public float getInterpolation(float input) {
if (mFactor == 1.0f) { // 默认: mFactor = 1.0f;
return input * input; // x^2
} else {
return (float)Math.pow(input, 2 * mFactor);
}
}
测试:在负方向一直减速递减到0,之后在正方向再一直加速递增
注:对函数公式的测试,可以采用之间博文:自定义安卓函数曲线控件,从曲线变化趋势得到速率变化
<C>android.view.animation.DecelerateInterpolator
decelerate
英 [diː'seləreɪt] 美 [,di'sɛləret] 全球发音 跟读 口语练习
vi. 减速,降低速度
vt. 使减速
public float getInterpolation(float input) {
float result;
if (mFactor == 1.0f) {
result = (float)(1.0f - (1.0f - input) * (1.0f - input));
} else {
result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));
}
return result;
}
测试:在1之前减幅递增,之后加幅递减
<C>android.view.animation.AccelerateDecelerateInterpolator
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
测试:2个数值之间为一个变化周期;在0到0.5之间为加幅递增,之后到1为减幅递增,之后又是加幅递减、减幅递减
<C>android.view.animation.CycleInterpolator
public float getInterpolation(float input) {
return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
测试:速率在0到大概0.5之间递增,之后到大概0.7为减速,之后到0.9为负向加速,在到1为负向加速到0
<C>android.view.animation.LinearInterpolator
public float getInterpolation(float input) {
return input;
}
效果:速率保持不变(动画进度与速率变化保持一致)
<C>android.view.animation.OvershootInterpolator
overshoot 报错
英 [əʊvə'ʃuːt] 美 [,ovɚ'ʃut] 跟读 口语练习
vt. 超越;打过头;把…做过头
vi. 射击越标;(飞机)滑出跑道;行动过火
n. 超越目标;行动过火
tension Amount of overshoot. When tension equals 0.0f, there is no overshoot and the interpolator becomes a simple deceleration interpolator.
超过的拉伸量。当拉伸为0时,这个插入器变成一个简单的减速插入器。
public float getInterpolation(float t) {
// _o(t) = t * t * ((tension + 1) * t + tension)
// o(t) = _o(t - 1) + 1
t -= 1.0f;
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
测试(mTension = 2.0f;):0到0.5减幅递增到大概1.2,之后到1为减速至1
应用测试:
(某移动动画)
anim.setDuration(300);
anim.setInterpolator(new Interpolator() {
@Override
public float getInterpolation(float input) {
System.out.println(input);
return input;
}
});
06-26 14:38:03.087: I/System.out(27427): 0.0
06-26 14:38:03.087: I/System.out(27427): 0.0
06-26 14:38:03.097: I/System.out(27427): 0.036666665
06-26 14:38:03.117: I/System.out(27427): 0.093333334
06-26 14:38:03.127: I/System.out(27427): 0.15
06-26 14:38:03.147: I/System.out(27427): 0.20666666
06-26 14:38:03.167: I/System.out(27427): 0.26333332
06-26 14:38:03.177: I/System.out(27427): 0.32
06-26 14:38:03.197: I/System.out(27427): 0.37666667
06-26 14:38:03.217: I/System.out(27427): 0.43333334
06-26 14:38:03.227: I/System.out(27427): 0.49
06-26 14:38:03.247: I/System.out(27427): 0.5466667
06-26 14:38:03.267: I/System.out(27427): 0.60333335
06-26 14:38:03.287: I/System.out(27427): 0.6566667
06-26 14:38:03.297: I/System.out(27427): 0.7133333
06-26 14:38:03.317: I/System.out(27427): 0.77
06-26 14:38:03.337: I/System.out(27427): 0.83
06-26 14:38:03.347: I/System.out(27427): 0.8833333
06-26 14:38:03.367: I/System.out(27427): 0.94
06-26 14:38:03.387: I/System.out(27427): 1.0
06-26 14:38:03.397: I/System.out(27427): 1.0
不同移动距离,300毫秒持续时间,插入器被调用总是21次。
修改getInterpolation实现为“return input*input;”,效果:动画在更短时间内达到位置
修改getInterpolation实现为“return input/2;”,效果:动画在指定时间内未达到位置,画面闪烁之后达到位置。
总结:
主要有三点:
1、Interpolator就是一个“变化率”,一个基本动画的“变化率”。
2、input是一个0.0f~1.0f的浮点类型
3、假设距离为S,时间为t,速度为v,都知道S=v*t
猜测Interpolator的工作原理是:
首先,动画需要将during持续时间分割,得到连续的时间片
然后,循环时间片,通过每个时间片的位置在整个持续时间的比值,即动画过程进度,再使用Interpolator得到一个即时速率
最后,用即时速率x时间片长度得到一次偏移量,即一帧前后图像的位置偏移量
有没有可能在动画时间尚未结束,而已经到达目的位置的可能?或动画时间结束时并未到达目的位置?
而且还有一个问题是:持续时间并不能总和实际的动画时间一致,那又对此如何处理呢?
猜测安卓采用的一种策略是:首先完成时间之间的动画过程,之后做后续的调整。
而观察以上所有插入器的特点得知:在0~1之间所经过的路径总是超过匀速通过的路径,即都保证了在动画结束时都可以达到指定位置。
最好的速率控制是:在相同时间内,自定义速率变化和匀速走过的路径是相同的。即就像两个人摩托一样,一个人保持匀速,一个人按照逻辑的变化速度(甚至晚会走),最后都同时达到,这个速度的控制逻辑就是最好的。
但设计一个函数公式时,不仅要考虑时间和面积,还要考虑移动端的运算性能,而事实上不可兼得也是可以理解的。
参考:
http://blog.sina.com.cn/s/blog_4a6c59d60100wznv.html (Android 动画之Interpolator插入器 )