在Android系统中,窗口动画的本质就是对原始窗口施加一个变换(Transformation)。在线性数学中,对物体的形状进行变换是通过乘以一个矩阵(Matrix)来实现,目的就是对物体进行偏移、旋转、缩放、切变、反射和投影等。因此,给窗口设置动画实际上就给窗口设置一个变换矩阵(Transformation Matrix)。
如前所述,一个窗口在打开(关闭)的过程,可能会被设置三个动画,它们分别是窗口本身所设置的进入(退出)动画(Self Transformation)、从被附加窗口传递过来的动画(Attached Transformation),以及宿主Activity组件传递过来的切换动画(App Transformation)。这三个Transformation组合在一起形成一个变换矩阵,以60fps的速度应用在窗口的原始形状之上,完成窗口的动画过程,如图1所示。
图1 窗口的动画显示过程
从上面的分析可以知道,窗口的变换矩阵是应用在窗口的原始位置和大小之上的,因此,在显示窗口的动画之前,除了要给窗口设置变换矩阵之外,还要计算好窗口的原始位置和大小,以及布局和绘制好窗口的UI。在前面Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析和Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析这两篇文章中,我们已经分析过窗口的位置和大小计算过程以及窗口UI的布局和绘制过程了,本文主要关注窗口动画的设置、合成和显示过程。这三个过程通过以下四个部分的内容来描述:
1. 窗口动画的设置过程
2. 窗口动画的显示框架
3. 窗口动画的推进过程
4. 窗口动画的合成过程
其中,窗口动画的设置过程包括上述三个动画的设置过程,窗口动画的推进过程是指定动画的一步一步地迁移的过程,窗口动画的合成过程是指上述三个动画组合成一个变换矩阵的过程,后两个过程包含在了窗口动画的显示框架中。
一. 窗口动画的设置过程
窗口被设置的动画虽然可以达到三个,但是这三个动画可以归结为两类,一类是普通动画,例如,窗口在打开过程中被设置的进入动画和在关闭过程中被设置的退出动画,另一类是切换动画。其中,Self Transformation和Attached Transformation都是属于普通动画,而App Transformation属于切换动画。接下来我们就分别分析这两种类型的动画的设置过程。
1. 普通动画的设置过程
从前面Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析一文可以知道,窗口在打开的过程中,是通过调用WindowState类的成员函数performShowLocked来实现的,如下所示:
[java]
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
......
private final class WindowState implements WindowManagerPolicy.WindowState {
......
boolean performShowLocked() {
......
if (mReadyToShow && isReadyForDisplay()) {
......
if (!showSu易做图ceRobustlyLocked(this)) {
return false;
}
......
applyEnterAnimationLocked(this);
......
}
return true;
}
......
}
......
}
这个函数定义在文件frameworks/base/services/java/com/android/server/WindowManagerService.java中。
WindowState类的成员函数performShowLocked首先是调用WindowManagerService类的成员函数showSu易做图ceRobustlyLocked来通知Su易做图ceFlinger服务将当前正在处理的窗口设置为可见,接着再调用WindowManagerService类的成员函数applyEnterAnimationLocked来给当前正在处理的窗口设置一个进入动画,如下所示:
[java]
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
......
private void applyEnterAnimationLocked(WindowState win) {
int transit = WindowManagerPolicy.TRANSIT_SHOW;
if (win.mEnterAnimationPending) {
win.mEnterAnimationPending = false;
transit = WindowManagerPolicy.TRANSIT_ENTER;
}
applyAnimationLocked(win, transit, true);
}
......
}
这个函数定义在文件frameworks/base/services/java/com/android/server/WindowManagerService.java中。
如果参数win所指向的一个WindowState对象的成员变量mEnterAnimationPending的值等于true,那么就说明它所描述的窗口正在等待显示,也就是正处于不可见到可见状态的过程中,那么WindowManagerService类的成员函数applyEnterAnimationLocked就会对该窗口设置一个类型为WindowManagerPolicy.TRANSIT_ENTER的动画,否则的话,就会对该窗口设置一个类型为WindowManagerPolicy.TRANSIT_SHOW的动画。
确定好窗口的动画类型之后,WindowManagerService类的成员函数applyEnterAnimationLocked就调用另外一个成员函数applyAnimationLocked来为窗口创建一个动画了。接下来我们先分析窗口在关闭的过程中所设置的动画类型,然后再来分析WindowManagerService类的成员函数applyAnimationLocked的实现。
从前面Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析一文可以知道,当应用程序进程请求WindowManagerService服务刷新一个窗口的时候,会调用到WindowManagerService类的成员函数relayoutWindow。WindowManagerService类的成员函数relayoutWindow在执行的过程中,如果发现需要将一个窗口从可见状态设置为不可见状态时,也就是发现需要关闭一个窗口时,就会对该窗口设置一个退出动出,如下所示:
[java]
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
......
public int relayoutWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending,
Rect outFrame, Rect o
补充:移动开发 , Android ,