1. 动画的基本原理
动画的本质是属性随时间变化的过程。例如,一个按钮从位置 A 移动到位置 B,需要不断计算每一帧的位置。Android 动画系统通过两个核心组件实现这一过程:
- 插值器(Interpolator):控制动画的“节奏”(如匀速、加速、弹跳)。
- 估值器(Evaluator):根据节奏计算“具体属性值”(如坐标、颜色)。
2. 插值器(Interpolator):时间的魔法师
想象插值器是一个“时间变速器”,它决定了动画在不同时间点的进度比例(比如前慢后快)。它的核心是数学函数,输入是时间进度(0~1),输出是“调整后的进度”(可能小于0或大于1)。
2.1 源码结构
所有插值器继承自 BaseInterpolator,核心方法是 getInterpolation(float input):
- 参数
input:动画已进行的时间比例(0 表示开始,1 表示结束)。 - 返回值:调整后的进度(例如输入 0.5,返回 0.25 表示此时进度只有 25%)。
2.2 常见插值器详解
-
Linear(线性)
- 效果:匀速动画。
- 公式:
y = t - 源码:直接返回输入值
input。
-
Accelerate(加速)
- 效果:速度越来越快。
- 公式:
y = t^(2×factor)(默认 factor=1,即t²)。 - 示例:
factor=2时,动画会更快达到高速。
-
Decelerate(减速)
- 效果:速度越来越慢。
- 公式:
y = 1 - (1 - t)^(2×factor)(默认1 - (1 - t)²)。
-
Bounce(弹跳)
-
效果:像球落地后弹跳几次。
-
实现:通过分段二次函数模拟弹跳轨迹,例如:
java Copy if (t < 0.3535) return 8*(1.1226t)^2; else if (t < 0.7408) return 8*(1.1226t - 0.54719)^2 + 0.7; ...
-
-
Anticipate(回拉)
- 效果:先向反方向移动一小段,再正向加速。
- 公式:
y = t² × ((tension+1)t - tension)(默认 tension=2)。
3. 估值器(Evaluator):数值的计算器
插值器决定了“进度比例”,估值器则根据这个比例计算具体的属性值。例如,从位置 0 移动到 100,进度 50% 时,估值器会计算出 50。
3.1 源码结构
所有估值器实现 TypeEvaluator<T> 接口,核心方法是:
java
Copy
T evaluate(float fraction, T startValue, T endValue);
- 参数
fraction:插值器调整后的进度(可能超出 0~1)。 - 参数
startValue,endValue:属性起始值和结束值。 - 返回值:当前属性值。
3.2 常见估值器
-
IntEvaluator(整数计算)
- 公式:
result = start + (end - start) * fraction - 示例:从 0 到 100,进度 0.5 时值为 50。
- 公式:
-
ArgbEvaluator(颜色渐变)
-
实现:将颜色拆分为 ARGB 四个通道,分别计算:
java Copy int red = startRed + (int)(fraction * (endRed - startRed)); // 同理计算 alpha、green、blue,再合并为最终颜色。
-
4. 协同工作流程
- 时间流逝:系统计算已进行的时间比例
t(如 0.5)。 - 插值器转换:通过
getInterpolation(t)得到新的进度fraction(可能被加速/减速)。 - 估值器计算:根据
fraction计算当前属性值(如位置、颜色)。
示例:一个按钮在 2 秒内从 (0,0) 移动到 (200,0),使用 BounceInterpolator:
- 时间过半(t=1秒),插值器可能返回
fraction=0.7(进度更快)。 - 估值器计算 X 坐标:
0 + 0.7 * (200-0) = 140,此时按钮已超过中点。
5. 设计思考
- 插值器的数学本质:通过函数曲线控制动画节奏,例如平方函数(
t²)让初始速度更慢。 - 为什么需要估值器?属性类型多样(位置、颜色、旋转角度),需要专用计算逻辑。
- ArgbEvaluator 的单例问题:虽然源码用单例,但构造方法未私有化,可能是框架内部优化,开发者无需关心。
6. 总结
- 插值器:决定动画“如何变化”(快慢、弹跳)。
- 估值器:决定动画“变化成什么值”(位置、颜色)。
- 组合使用:通过不同的插值器和估值器,可以实现丰富的动画效果,例如颜色渐变的加速效果,或旋转时的回弹。