8.1、window和windowManager
为了分析window的工作机制,我们需要先了解如何使用windowManager添加一个window
代码如下:
WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(width,height,type,flags,format);
manager.addView(btn, layoutParams);
是不是很简单的说?
LayoutParams中type和flags比较重要
flags有很多选项,来控制window的显示特性,我们看几个常用的
public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
表示此window不需要获取焦点,不接收各种输入事件,此标记是会同时启用FLAG_NOT_TOUCH_MODAL
最终事件会直接传递给下层具有焦点的window
public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
自己window区域内的事件,自己处理;自己区域外的事件传递给底层window处理;
一般这个都会默认开启,不然其他window无法收到事件
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
可以让此window显示在锁屏上
type表示window的类型,window有3种类型,应用window,子window,系统window
window是分层的,层级大的view会覆盖在层级小的view上面
应用window的层级范围:1~99
子window的层级范围:1000~1999
系统window的层级范围:2000~2999
这些层级返回对应type参数,如果想要window至于最顶层,采用较大的层级即可
同时如果是系统类型的window是需要在menifest中配置权限的:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
下面我们来看看windowManager:
它是一个接口,继承ViewManager:
public interface WindowManager extends ViewManager {
ViewManager中只有3个方法:
public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
根据方法名称就可以知道是对view的增加、修改、删除
8.2、window的内部机制
每个window都对应一个view和viewrootimpl
8.2.1、window的添加过程
window的添加是通过windowManager来实现的
windowManager是一个接口,它的实现类是:windowManagerImpl
我们来看看WindowManagerImpl这个类:
找到了我们需要的方法:
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
}
我们可以看到它是利用了工厂类WindowManaerGlobal来实现的
WindowManaerGlobal实现addview分如下几步:
1、检查参数是否合法,如果是子window,那么还需要调整一些布局参数
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException(