一、开始
调用View.startAnimation
开始运行动画。
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
这个方法很简单,主要做了两件事:
- 将动画赋值给当前View的
mCurrentAnimation
变量; - 标记当前的View需要重绘;
二、运行中
2.1 前期
在Choreographer接收到vsync信号后,回调给ViewRootImpl,开始刷新界面。
经过一系列的调用,最终,会进入到View的draw(Canvas canvas, ViewGroup parent, long drawingTime)
方法中。
这个过程比较长,涉及到的类有Choreographer -> ViewRootImpl -> ThreadRenderer -> ViewGroup -> View。
2.2 View
View的draw(Canvas canvas, ViewGroup parent, long drawingTime)
方法会调用applyLegacyAnimation
方法,该方法又会调用Animation的getTransformation
方法。
2.3 Animation
在Animation.getTransformation
中,会进行一系列的处理,将当前时间根据设置的插值器转换为插值时间,并最终调用applyTransformation
方法。这是动画实现核心逻辑的地方。根据applyTransformation
的具体实现,就可以完成动画在当前帧的动作。
applyTransformation
接收2个参数,第一个是插值时间,相当于动画完成的百分比;第二个是一个Transformation
对象,通过操作这个对象来实现动画。
例如,AlphaAnimation.applyTransformation
方法实现如下:
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
ScaleAnimation.applyTransformation
方法实现如下:
protected void applyTransformation(float interpolatedTime, Transformation t) {
float sx = 1.0f;
float sy = 1.0f;
float scale = getScaleFactor();
if (mFromX != 1.0f || mToX != 1.0f) {
sx = mFromX + ((mToX - mFromX) * interpolatedTime);
}
if (mFromY != 1.0f || mToY != 1.0f) {
sy = mFromY + ((mToY - mFromY) * interpolatedTime);
}
if (mPivotX == 0 && mPivotY == 0) {
t.getMatrix().setScale(sx, sy);
} else {
t.getMatrix().setScale(sx, sy, scale * mPivotX, scale * mPivotY);
}
}
三、结束
在 2.2 中的applyLegacyAnimation
方法会返回一个boolean值,标记了动画是否还要继续执行。如果该值为false,表示动画需要结束。
如果标记需要结束动画,则View会执行parent.finishAnimatingView
方法。在其父布局中,又会调用view.clearAnimation
方法。也就是说,最终调用的是View的clearAnimation
方法。在其中,会将mCurrentAnimation
变量置为null。
四、总结
- Choreographer类会监听设备的vsync信号,在每一帧刷新的时候,收到回调。
- 当收到回调后,Choreographer会通知ViewRootImpl刷新视图树。
- 刷新视图树会调用
View.draw(canvas, parent, time)
方法。 -
View.draw(canvas, parent, time)
最终会调用Animation.getTransformation
方法。 -
Animation的
getTransformation
中会调用applyTransformation
方法,Animation子类在其中完成动画的具体实现。
网友评论