WindowManager

作者: richy_ | 来源:发表于2018-04-23 19:54 被阅读47次

Window、WindowManager 和 WMS

Window 是一个抽象类,具体实现是PhoneWindow,它对View进行管理。

WindowManager 是一个接口,继承自 ViewManager ,具体实现类是 WindowManagerImpl, 它是用来管理Window的, 对window的添加、删除都有它处理。

WMS(WindowManagerService) 是功能实现服务包括 Window 的功能实现和输入系统,WindowManager 和 WMS 通过 Binder 来进行跨进程通信。

img

Window 包含了 View 并对 View 进行管理,Window 用虚线来表示是因为 Window 是一个抽象概念,并不是真实存在,Window 的实体其实也是 View。WindowManager 用来管理 Window,而 WindowManager 所提供的功能最终会由 WMS 来进行处理。

WindowManager 体系

//frameworks/base/core/java/android/view/WindowManager.java
public void addView(View view, ViewGroup.LayoutParams params);//添加View
public void updateViewLayout(View view, ViewGroup.LayoutParams params);//更新View
public void removeView(View view);//删除View
public Display getDefaultDisplay();//得到 WindowManager 所管理的屏幕(Display)
public void removeViewImmediate(View view);//在这个方法返回前要立即执行View.onDetachedFromWindow(),来完成传入的 View 的销毁工作

除了一些常用方法,WM还有包括 Window 的类型和层级相关的常量、内部类以及一些方法。

Activity到绑定Window

绑定window.png

WindowManager的结构图

WindowManager.png

Window 的属性

Type(Window 的类型)、Flag(Window 的标志) 和 SoftInputMode(软键盘相关模式)

Window 类型

Window 的类型有很多种,比如应用程序窗口、系统错误窗口、输入法窗口、PopupWindow、Toast、Dialog 等等。总来来说分为三大类分别是:Application Window(应用程序窗口)、Sub Windwow(子窗口)、System Window(系统窗口),每个大类又包含了很多种类型,它们都定义在 WindowManager 的静态内部类 LayoutParams 中。

// 应用程序窗口1~99
public static final int FIRST_APPLICATION_WINDOW = 1;//1
public static final int TYPE_BASE_APPLICATION   = 1;//窗口的基础值,其他的窗口值要大于这个值
public static final int TYPE_APPLICATION        = 2;//普通的应用程序窗口类型
public static final int TYPE_APPLICATION_STARTING = 3;//应用程序启动窗口类型,用于系统在应用程序窗口启动前显示的窗口。
public static final int TYPE_DRAWN_APPLICATION = 4;
public static final int LAST_APPLICATION_WINDOW = 99;//2
//子窗口1000~1999,它不能独立的存在,需要附着在其他窗口才可以,如PopupWindow
public static final int FIRST_SUB_WINDOW = 1000;//子窗口类型初始值
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4; 
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
public static final int LAST_SUB_WINDOW = 1999;//子窗口类型结束值
//系统窗口2000~2999 如Toast、输入法窗口、系统音量条窗口、系统错误窗口
public static final int FIRST_SYSTEM_WINDOW     = 2000;//系统窗口类型初始值
public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;//系统状态栏窗口
public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;//搜索条窗口
public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;//通话窗口
public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;//系统ALERT窗口
public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;//锁屏窗口
public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;//TOAST窗口
...
public static final int LAST_SYSTEM_WINDOW      = 2999;//系统窗口类型结束值

窗口显示次序

当一个进程向 WMS 申请一个窗口时,WMS 会为窗口确定显示次序。

为了方便窗口显示次序的管理,手机屏幕可以虚拟的用 X、Y、Z 轴来表示,其中 Z 轴垂直于屏幕,从屏幕内指向屏幕外,这样确定窗口显示次序也就是确定窗口在 Z 轴上的次序,这个次序称为 Z-Oder。Type 值是 Z-Oder 排序的依据,我们知道应用程序窗口的 Type 值范围为 1 到 99,子窗口 1000 到 1999 ,系统窗口 2000 到 2999,,一般情况下,Type 值越大则 Z-Oder 排序越靠前,就越靠近用户。

窗口的Z次序管理

Window 的标志

定义在WindowManager 的内部类 LayoutParams 中

FLAG 描述
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON 只要窗口可见,就允许在开启状态的屏幕上锁屏
FLAG_NOT_FOCUSABLE 窗口不能获得输入焦点,设置该标志的同时,FLAG_NOT_TOUCH_MODAL 也会被设置
FLAG_NOT_TOUCHABLE 窗口不接收任何触摸事件
FLAG_NOT_TOUCH_MODAL 在该窗口区域外的触摸事件传递给其他的 Window, 而自己只会处理窗口区域内的触摸事件
FLAG_KEEP_SCREEN_ON 只要窗口可见,屏幕就会一直亮着
FLAG_LAYOUT_NO_LIMITS 允许窗口超过屏幕之外
FLAG_FULLSCREEN 隐藏所有的屏幕装饰窗口,比如在游戏、播放器中的全屏显示
FLAG_SHOW_WHEN_LOCKED 窗口可以在锁屏的窗口之上显示
FLAG_IGNORE_CHEEK_PRESSES 当用户的脸贴近屏幕时(比如打电话),不会去响应此事件
FLAG_TURN_SCREEN_ON 窗口显示时将屏幕点亮

设置Flag的相关方法

Window mWindow =getWindow(); 
//第一种
mWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
//第二种
mWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//第三种 给 LayoutParams 设置 Flag,然后通过 WindowManager 的 addView 方法进行添加
WindowManager.LayoutParams mWindowLayoutParams = new WindowManager.LayoutParams();
mWindowLayoutParams.flags=WindowManager.LayoutParams.FLAG_FULLSCREEN;
WindowManager mWindowManager =(WindowManager) getSystemService(Context.WINDOW_SERVICE);  
TextView mTextView=new TextView(this);
mWindowManager.addView(mTextView,mWindowLayoutParams);

软键盘相关模式

在WindowManager 的静态内部类 LayoutParams 中定义了软键盘相关模式

SOFTINPUTMODE 描述
SOFT_INPUT_STATE_UNSPECIFIED 没有指定状态, 系统会选择一个合适的状态或依赖于主题的设置
SOFT_INPUT_STATE_UNCHANGED 不会改变软键盘状态
SOFT_INPUT_STATE_HIDDEN 当用户进入该窗口时,软键盘默认隐藏
SOFT_INPUT_STATE_ALWAYS_HIDDEN 当窗口获取焦点时,软键盘总是被隐藏
SOFT_INPUT_ADJUST_RESIZE 当软键盘弹出时,窗口会调整大小
SOFT_INPUT_ADJUST_PAN 当软键盘弹出时,窗口不需要调整大小,要确保输入焦点是可见的
//android:windowSoftInputMode
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

Window 的添加过程

Window 的添加过程

对于不同类型的窗口添加过程会有所不同,但是对于 WMS 处理部分,添加的过程基本上是一样的。所以先分析 WindowManager 的处理部分,之后再集中分析WMS的处理。

系统窗口的添加过程

以系统窗口 StatusBar 为例

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

ViewRootImpl

ViewRootImpl 身负了很多职责:implementing the needed protocol between View* and the WindowManager

  • View 树的根并管理 View 树
  • 触发 View 的测量、布局和绘制
  • 输入事件的中转站
  • 管理 Surface
  • 负责与 WMS 进行进程间通信
系统窗口添加过程.png

Activity 的添加过程

Activity添加过程.png

相关文章

网友评论

    本文标题:WindowManager

    本文链接:https://www.haomeiwen.com/subject/iptrlftx.html