对我来说,Android的Window窗口机制是一大难点,特别是里面涉及到的类与类都非常相似,所以花了一段时间来理解梳理Window、 ViewRootImpl、WindowManagerService(后文简称WMS)之间的关系。
按照习惯,先抛出自己一开始的问题:
- Android window 是怎么使用的?
- Window、View、WMS以及ViewRootImpl之间什么关系?
这是我一开始的疑惑,后面随着学习深入,慢慢地把第二个问题分解成几个部分:
- Activity、WindowManager、Window之间怎么关联
- DecorView、PhoneWindow之间怎么关联(setContentView)
- Activity 怎么创建添加一个Window(从App进程的角度看)
- WMS 怎么创建添加一个Window (从WMS进程的角度看)
- Token的创建和作用
先给一张最后的流程图
利用WindowManager创建Window
受《Android艺术开发探索》启发,从创建Window的例子开始窥探Android的窗口机制。
// MainActivity
private void checkAndCreate() {
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, 1);
} else {
createFloatButton();
}
}
}
// MainActivity
private void createFloatButton() {
Button mFloatingButton = new Button(this);
mFloatingButton.setText("click me");
WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0,
PixelFormat.TRANSPARENT);
mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;
getWindowManager().