Android 动画原理
Android 动画过程中:在某一个时间点,调用 getTransformation()
根据 mStartTime 和 mDuration , 计算出当前的进度。
再根据 mInterpolator 计算出转换的进度,然后计算出属性的当前值,保存在 matrix 中。
再调用 Matrix.getValues 将属性值取出,运用在动画目标上。
Animation 和 Transfrom
Animtaion
在给定了初始状态
SurfaceAnimator.java
41 /**
42 * A class that can run animations on objects that have a set of child surfaces. We do this by
43 * reparenting all child surfaces of an object onto a new surface, called the "Leash". The Leash
44 * gets attached in the surface hierarchy where the the children were attached to. We then hand off
45 * the Leash to the component handling the animation, which is specified by the
46 * {@link AnimationAdapter}. When the animation is done animating, our callback to finish the
47 * animation will be invoked, at which we reparent the children back to the original parent.
48 */
49 class SurfaceAnimator {
该类可以针对那种存在多个child surface 的对象进行动画,在执行动画的过程中会创建一个没有 Buffer 的 Surface -- "Leash" , 将所有 child surface 绑定到 leash 上,leash 同时也会绑定到原先这些 child surface 绑定的位置。
然后我们将 leash 给到 AnimationAdaoter 去执行动画,执行动画结束后会将所有 child surface 重新绑定到原先的父节点上。
startAnimation@SurfaceAnimator.java
122 /**
123 * Starts an animation.
124 *
125 * @param anim The object that bridges the controller, {@link SurfaceAnimator}, with the
126 * component responsible for running the animation. It runs the animation with
127 * {@link AnimationAdapter#startAnimation} once the hierarchy with
128 * the Leash has been set up.
129 * @param hidden Whether the container holding the child surfaces is currently visible or not.
130 * This is important as it will start with the leash hidden or visible before
131 * handing it to the component that is responsible to run the animation.
132 * @param animationFinishedCallback The callback being triggered when the animation finishes.
133 */
134 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
135 @AnimationType int type,
136 @Nullable OnAnimationFinishedCallback animationFinishedCallback,
137 @Nullable SurfaceFreezer freezer) {
138 cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
139 mAnimation = anim;
140 mAnimationType = type;
141 mAnimationFinishedCallback = animationFinishedCallback;
// step1. 先获取当前需要执行动画的对象的 surface
142 final SurfaceControl surface = mAnimatable.getSurfaceControl();
143 if (surface == null) {
144 Slog.w(TAG, "Unable to start animation, surface is null or no children.");
145 cancelAnimation();
146 return;
147 }
// step2.根据 freezer 来构建一个 Leash
148 mLeash = freezer != null ? freezer.takeLeashForAnimation() : null;
149 if (mLeash == null) {
150 mLeash = createAnimationLeash(mAnimatable, surface, t, type,
151 mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
152 0 /* y */, hidden, mService.mTransactionFactory);
153 mAnimatable.onAnimationLeashCreated(t, mLeash);
154 }
155 mAnimatable.onLeashAnimationStarting(t, mLeash);
156 if (mAnimationStartDelayed) {
157 if (DEBUG_ANIM) Slog.i(TAG, "Animation start delayed");
158 return;
159 }
160 if (mAnimation != null) {
// step3.将 Leash 传给 AnimationAdapter , 启动动画
161 mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
162 }
163 }
164
这里的 startAnimation 的第一个参数是 Transaction ,所以一定是在 打开一次 transaction 的情况下开始启动动画的。
step1. 这个 getSurfaceControl 是 Animatable 这个 Interface 中的一个接口,所有能够执行动画的对象都需要实现这个 interface 。
599 /**
600 * @return The surface of the object to be animated.
601 * This SurfaceControl must be valid if non-null.
602 */
603 @Nullable SurfaceControl getSurfaceControl();
step2. 创建 Leash (leash 就是狗绳的意思,就是有用这个leash 拴住这些 child surface 来跑动画,在SF中这些 layer 的层次结构不会出现异常)
386 static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface,
387 Transaction t, @AnimationType int type, int width, int height, int x, int y,
388 boolean hidden, Supplier<Transaction> transactionFactory) {
389 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
// step2.1 通过 makeAnimationLeash 构造这个 Surface
390 final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
391 .setParent(animatable.getAnimationLeashParent())
392 .setName(surface + " - animation-leash of " + animationTypeToString(type))
393 // TODO(b/151665759) Defer reparent calls
394 // We want the leash to be visible immediately because the transaction which shows
395 // the leash may be deferred but the reparent will not. This will cause the leashed
396 // surface to be invisible until the deferred transaction is applied. If this
397 // doesn't work, you will can see the 2/3 button nav bar flicker during seamless
398 // rotation.
399 .setHidden(hidden)
400 .setEffectLayer()
401 .setCallsite("SurfaceAnimator.createAnimationLeash");
402 final SurfaceControl leash = builder.build();
// step2.2 设置 transaction 相关参数,show 和 reparent
// show : 这次 transaction 中显示 leash
// reparent: 将leash reparent 到当前 Surface 的父节点上
403 t.setWindowCrop(leash, width, height);
404 t.setPosition(leash, x, y);
405 t.show(leash);
406 t.setAlpha(leash, hidden ? 0 : 1);
407
408 t.reparent(surface, leash);
409 return leash;
410 }
step2.1 创建 leash
在 WindowContaoner.java 中,递归调用到根节点到 DisplayContent 中
2543 @Override
2544 public Builder makeAnimationLeash() {
2545 return makeSurface().setContainerLayer();
2546 }
2195 SurfaceControl.Builder makeSurface() {
2196 final WindowContainer p = getParent();
2197 return p.makeChildSurface(this);
2198 }
2200 /**
2201 * @param child The WindowContainer this child surface is for, or null if the Surface
2202 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
2203 */
2204 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
2205 final WindowContainer p = getParent();
2206 // Give the parent a chance to set properties. In hierarchy v1 we rely
2207 // on this to set full-screen dimensions on all our Surface-less Layers.
2208 return p.makeChildSurface(child)
2209 .setParent(mSurfaceControl);
2210 }
在DisplayContent 中
4828 @Override
4829 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
4830 SurfaceSession s = child != null ? child.getSession() : getSession();
// 通过 wms 来创建实际的 SurfaceControl , 然后层层返回,最终这个 Surface 绑定到最早调用启动动画的对象上
4831 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
4832 if (child == null) {
4833 return b;
4834 }
4835
4836 return b.setName(child.getName())
4837 .setParent(mSurfaceControl);
4838 }
4839
Step2. 使用 AnimationAdapter 启动动画
// frameworks/base/services/core/java/com/android/server/wm/AnimationAdapter.java
43 /**
44 * Requests to start the animation.
45 *
46 * @param animationLeash The surface to run the animation on. See {@link SurfaceAnimator} for an
47 * overview of the mechanism. This surface needs to be released by the
48 * component running the animation after {@code finishCallback} has been
49 * invoked, or after the animation was cancelled.
50 * @param t The Transaction to apply the initial frame of the animation.
51 * @param type The type of the animation.
52 * @param finishCallback The callback to be invoked when the animation has finished.
53 */
54 void startAnimation(SurfaceControl animationLeash, Transaction t, @AnimationType int type,
55 OnAnimationFinishedCallback finishCallback);
LocalAnimationAdapter 就是对 AnimationAdapter 的实现:
// frameworks/base/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
32 /**
33 * Animation that can be executed without holding the window manager lock. See
34 * {@link SurfaceAnimationRunner}.
35 */
36 class LocalAnimationAdapter implements AnimationAdapter {
...
52 @Override
53 public void startAnimation(SurfaceControl animationLeash, Transaction t,
54 @AnimationType int type, OnAnimationFinishedCallback finishCallback) {
55 mAnimator.startAnimation(mSpec, animationLeash, t,
56 () -> finishCallback.onAnimationFinished(type, this));
57 }
这里用于执行动画的 mAnimator 的类型是 SurfaceAnimationRunner ,在构造 AnimationAdapter 的时候会传入 SurfaceAnimationRuner,这个类会去执行动画。
42 LocalAnimationAdapter(AnimationSpec spec, SurfaceAnimationRunner animator) {
43 mSpec = spec;
44 mAnimator = animator;
45 }
每一个 WC 对应一个 SA , 当一个 WC 需要执行一个特定动画的时候,只需要传入一个 AD 来指定特定的动画即可,而动画执行的线程都是在 AD 的构造中创建。
SurfaceAnimationRunner
//frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
134 void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
135 Runnable finishCallback) {
136 synchronized (mLock) {
// step1. 使用spec,leash,动画结束后的回调构造一个RunningAnimation,这个类相当于一个动画的记录
137 final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
138 finishCallback);
139 mPendingAnimations.put(animationLeash, runningAnim);
// step2. 往编舞者上抛一个回调
140 if (!mAnimationStartDeferred) {
141 mChoreographer.postFrameCallback(this::startAnimations);
142 }
143
144 // Some animations (e.g. move animations) require the initial transform to be applied
145 // immediately.
146 applyTransformation(runningAnim, t, 0 /* currentPlayTime */);
147 }
148 }
从这个来看这个 Runner 是可以复用的,构造一个然后将多个 RunningAnimation 放在上面运行,因为 Runner 中维护了一个列表可以存储多个 Animation.
往编舞者上面抛的回调是 startAnimations
170 @GuardedBy("mLock")
171 private void startPendingAnimationsLocked() {
172 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
173 startAnimationLocked(mPendingAnimations.valueAt(i));
174 }
175 mPendingAnimations.clear();
176 }
177
从上面可以看出,将pending的动画全部拿出来执行,然后清空掉 pending 的列表
178 @GuardedBy("mLock")
179 private void startAnimationLocked(RunningAnimation a) {
// step1. 创建一个 valueanimator
180 final ValueAnimator anim = mAnimatorFactory.makeAnimator();
181 // step2. 根据AnimationSpec 设置这个 VA 的属性以及注册回调函数
182 // Animation length is already expected to be scaled.
183 anim.overrideDurationScale(1.0f);
184 anim.setDuration(a.mAnimSpec.getDuration());
185 anim.addUpdateListener(animation -> { // 这个是动画更新的回调
186 synchronized (mCancelLock) {
187 if (!a.mCancelled) {
188 final long duration = anim.getDuration();
189 long currentPlayTime = anim.getCurrentPlayTime();
190 if (currentPlayTime > duration) {
191 currentPlayTime = duration;
192 }
193 applyTransformation(a, mFrameTransaction, currentPlayTime);
194 }
195 }
196
197 // Transaction will be applied in the commit phase.
198 scheduleApplyTransaction(); // 在下一次Vsync 信号到来的时候使前面的修改生效
199 });
200
201 anim.addListener(new AnimatorListenerAdapter() {
202 @Override
203 public void onAnimationStart(Animator animation) {
204 synchronized (mCancelLock) {
205 if (!a.mCancelled) {
206 // TODO: change this back to use show instead of alpha when b/138459974 is
207 // fixed.
208 mFrameTransaction.setAlpha(a.mLeash, 1); // 动画开始的时候显示Leash这个Surface
209 }
210 }
211 }
212
213 @Override
214 public void onAnimationEnd(Animator animation) {
215 synchronized (mLock) {
216 mRunningAnimations.remove(a.mLeash);
217 synchronized (mCancelLock) {
218 if (!a.mCancelled) {
219
220 // Post on other thread that we can push final state without jank.
221 mAnimationThreadHandler.post(a.mFinishCallback);
222 }
223 }
224 }
225 }
226 });
227 a.mAnim = anim;
// step3. 加入到正在运行的动画 map 中
228 mRunningAnimations.put(a.mLeash, a);
229 // step4. 调用VA的start,动画的执行是依赖于VA本身的执行框架(ValueAnimation)
230 anim.start();
231 if (a.mAnimSpec.canSkipFirstFrame()) {
232 // If we can skip the first frame, we start one frame later.
233 anim.setCurrentPlayTime(mChoreographer.getFrameIntervalNanos() / NANOS_PER_MS);
234 }
235
236 // Immediately start the animation by manually applying an animation frame. Otherwise, the
237 // start time would only be set in the next frame, leading to a delay.
238 anim.doAnimationFrame(mChoreographer.getFrameTime());
239 }
step1. 这里创建的是一个 ValueAnimator 来 执行动画
step2. 设置 ValueAnimator 的回调函数
step3. 将该动画加到一个正在运行的 animation map 中
step4. 调用 start 开始动画