在Android系统中,壁纸窗口和输入法窗口一样,都是一种特殊类型的窗口,而且它们都是喜欢和一个普通的Activity窗口缠绵在一起。大家可以充分地想象这样的一个3W场景:输入法窗口在上面,壁纸窗口在下面,Activity窗口夹在它们的中间。在前面一篇文章中,我们已经分析过输入法窗口是如何压在Activity窗口上面的了。在这篇文章中,我们就将继续分析壁纸窗口是如何贴在Activity窗口下面的。
老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!
一个Activity窗口如果需要显示壁纸,那么它必须满足以下两个条件:
1. 背景是半透明的,例如,它在AndroidManifest.xml文件中的android:theme属性设置为Theme.Translucent:
[html]
<activity android:name=".Wall易做图Activity"
android:theme="@android:style/Theme.Translucent">
......
</activity>
2. 窗口属性中的WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER位设置为1:
[java]
public class Wall易做图Activity extends Activity {
......
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
}
......
}
满足了以上两个条件之后,Activity窗口和壁纸窗口的位置关系就如图1所示:
图1 Activity窗口和Wall易做图窗口的位置关系
在前面Android窗口管理服务WindowManagerService组织窗口的方式分析一文中提到,WindowManagerService服务是使用堆栈来组织系统中的窗口的,因此,如果我们在窗口堆栈中观察Activity窗口和壁纸窗口,它们的位置关系就如图2所示:
图2 Activity窗口和Wall易做图窗口在窗口堆栈中的位置关系
图2中的对象的关系如下所示:
1. 在ActivityManagerService服务内部的Activity组件堆栈顶端的ActivityRecord对象N描述的是系统当前激活的Activity组件。
2. ActivityRecord对象N在WindowManagerService服务内部的窗口令牌列表顶端对应有一个AppWindowToken对象N。
3. AppWindowToken对象N在WindowManagerService服务内部的窗口堆栈中对应有一个WindowState对象N,用来描述系统当前激活的Activity组件窗口。
4. WindowState对象N下面有一个WindowState对象WP,用来描述系统中的壁纸窗口。
5. 系统中的壁纸窗口在WindowManagerService服务内部中对应的窗口令牌是由WindowToken对象WP来描述的。
6. WindowToken对象WP在Wall易做图ManagerService服务中对应有一个Binder对象。
总的来说,就是图2描述了系统当前激活的Activity窗口需要显示壁纸的情景。WindowManagerService服务的职能之一就是要时刻关注系统中是否有窗口需要显示壁纸。WindowManagerService服务一旦发现有窗口需要显示壁纸,那么就会调整壁纸窗口在窗口堆栈中的位置,使得它放置在需要显示壁纸的窗口的下面。此外,需要显示壁纸的窗口还可以设置壁纸窗口在X轴和Y轴上的偏移位置,以便可以将壁纸窗口的某一部分指定为它的背景。
接下来,我们就首先分析两个需要调整壁纸窗口在窗口堆栈中的位置的情景,然后再分析壁纸窗口在X轴和Y轴上的偏移位置的调整过程,最后分析壁纸窗口在窗口堆栈中的位置调整过程。
一. 调整壁纸窗口在窗口堆栈中的位置的情景
第一个需要调整壁纸窗口在窗口堆栈中的位置的情景是增加一个窗口到WindowManagerService服务去的时候。从前面Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析一文可以知道,增加一个窗口到WindowManagerService服务最终是通过调用WindowManagerService类的成员函数addWindow来实现的。接下来我们就主要分析这个函数中与壁纸窗口调整相关的逻辑,如下所示:
[java]
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
......
public int addWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int viewVisibility,
Rect outContentInsets, InputChannel outInputChannel) {
......
synchronized(mWindowMap) {
......
WindowToken token = mTokenMap.get(attrs.token);
if (token == null) {
......
if (attrs.type == TYPE_WALLPAPER) {
......
return WindowManagerImpl.ADD_BAD_APP_TOKEN;
}
......
}
......
win = new WindowState(session, client, token,
attachedWindow, attrs, viewVisibility);
......
if (attrs.type == TYPE_INPUT_METHOD) {
......
} else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
......
} else {
addWindowToListInOrderLocked(win, true);
if (attrs.type == TYPE_WALLPAPER) {
......
adjustWall易做图WindowsLocked();
} else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
adjustWall易做图WindowsLocked();
}
}
......
assignLay
补充:移动开发 , Android ,