导航号,我的单页导航
文章目录

前言

记录一下AndroidWindowManger的层级相关知识。

摘抄于此,方便自己查阅。

本文摘抄于《Android中WindowManger的层级分析

正文

Window 分类

  1. 应用 Window(ApplicationWindow: 对应一个 Acitivity)
  2. 子 Window (SubWindow:不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog 就是一个子 Window)
  3. 系统 Window (SystemWindow:需要声明权限才能创建的 Window,比如 Toast 和系统状态栏都是系统 Window)

Window层级

Window 是分层的,每个 Window 都有对应的 z-ordered,层级大的会覆盖在层级小的Window上面。

每一种Window的层级范围也是不同的,如下:

1. 应用Window      1~99
2. 子Window        1000~1999
3. 系统Window      2000~2999

这些层级范围对应着WindowManager.LayoutParams的 type 参数.

如果想要Window位于所有Window 的最顶层,那么采用较大的层级即可,很显然系统Windo的层级是最大的,当我们采用系统层级时,需要声明权限。

窗口显示顺序:Type 值越大层级越高,Type 值大的覆盖 Type 值小的,这只是一般规律。

应用程序窗口
public static final int FIRST_APPLICATION_WINDOW = 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;
子窗口
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;
系统窗口
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;
public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;
public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;
public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;
public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;
public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;
public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;
public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22;
public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26;
public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;
public static final int TYPE_PRIVATE_PRESENTATION = FIRST_SYSTEM_WINDOW+30;
public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31;
public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;
public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34;
public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35;
public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;
public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37;
public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38;
public static final int LAST_SYSTEM_WINDOW      = 2999;

有些被影藏(@hide),有些被废弃,如果是系统应用,影藏的TYPE也是可以用的。

Window 的优先级

代码路径

/frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java

涉及方法getWindowLayerFromTypeLw()

default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
    if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
        return APPLICATION_LAYER;
    }
    switch (type) {
        case TYPE_WALLPAPER:
            // wallpaper is at the bottom, though the window manager may move it.
            return  1;
        case TYPE_PRESENTATION:
        case TYPE_PRIVATE_PRESENTATION:
            return  APPLICATION_LAYER;
        case TYPE_DOCK_DIVIDER:
            return  APPLICATION_LAYER;
        case TYPE_QS_DIALOG:
            return  APPLICATION_LAYER;
        case TYPE_PHONE:
            return  3;
        case TYPE_SEARCH_BAR:
        case TYPE_VOICE_INTERACTION_STARTING:
            return  4;
        case TYPE_VOICE_INTERACTION:
            // voice interaction layer is almost immediately above apps.
            return  5;
        case TYPE_INPUT_CONSUMER:
            return  6;
        case TYPE_SYSTEM_DIALOG:
            return  7;
        case TYPE_TOAST:
            // toasts and the plugged-in battery thing
            return  8;
        case TYPE_PRIORITY_PHONE:
            // SIM errors and unlock.  Not sure if this really should be in a high layer.
            return  9;
        case TYPE_SYSTEM_ALERT:
            // like the ANR / app crashed dialogs
            return  canAddInternalSystemWindow ? 11 : 10;
        case TYPE_APPLICATION_OVERLAY:
            return  12;
        case TYPE_DREAM:
            // used for Dreams (screensavers with TYPE_DREAM windows)
            return  13;
        case TYPE_INPUT_METHOD:
            // on-screen keyboards and other such input method user interfaces go here.
            return  14;
        case TYPE_INPUT_METHOD_DIALOG:
            // on-screen keyboards and other such input method user interfaces go here.
            return  15;
        case TYPE_STATUS_BAR:
            return  17;
        case TYPE_STATUS_BAR_PANEL:
            return  18;
        case TYPE_STATUS_BAR_SUB_PANEL:
            return  19;
        case TYPE_KEYGUARD_DIALOG:
            return  20;
        case TYPE_VOLUME_OVERLAY:
            // the on-screen volume indicator and controller shown when the user
            // changes the device volume
            return  21;
        case TYPE_SYSTEM_OVERLAY:
            // the on-screen volume indicator and controller shown when the user
            // changes the device volume
            return  canAddInternalSystemWindow ? 22 : 11;
        case TYPE_NAVIGATION_BAR:
            // the navigation bar, if available, shows atop most things
            return  23;
        case TYPE_NAVIGATION_BAR_PANEL:
            // some panels (e.g. search) need to show on top of the navigation bar
            return  24;
        case TYPE_SCREENSHOT:
            // screenshot selection layer shouldn't go above system error, but it should cover
            // navigation bars at the very least.
            return  25;
        case TYPE_SYSTEM_ERROR:
            // system-level error dialogs
            return  canAddInternalSystemWindow ? 26 : 10;
        case TYPE_MAGNIFICATION_OVERLAY:
            // used to highlight the magnified portion of a display
            return  27;
        case TYPE_DISPLAY_OVERLAY:
            // used to simulate secondary display devices
            return  28;
        case TYPE_DRAG:
            // the drag layer: input for drag-and-drop is associated with this window,
            // which sits above all other focusable windows
            return  29;
        case TYPE_ACCESSIBILITY_OVERLAY:
            // overlay put by accessibility services to intercept user interaction
            return  30;
        case TYPE_SECURE_SYSTEM_OVERLAY:
            return  31;
        case TYPE_BOOT_PROGRESS:
            return  32;
        case TYPE_POINTER:
            // the (mouse) pointer layer
            return  33;
        default:
            Slog.e("WindowManager", "Unknown window type: " + type);
            return APPLICATION_LAYER;
    }
}

返回的值越大,层级越高。

层级高低具体分析(对比Toast以及软键盘)

  1. 低于toast--->盖不住toast
  2. 低于软键盘--->盖不住软键盘
  3. 依附Activity使用--->is your activity running?
 public static int getWindowType(int num) {
    switch (num) {
        case 1:
        	//低于toast  低于软键盘
            return WindowManager.LayoutParams.TYPE_PHONE;
        case 2:
            //低于toast  低于软键盘
            return WindowManager.LayoutParams.TYPE_SEARCH_BAR;
        case 3:
        	//低于toast  低于软键盘
            return WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
        case 4:
        	//高于toast  低于软键盘
            return WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
        case 5:
        	//高于toast  低于软键盘
            return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        case 6:
        	//高于toast  盖住键盘
            return WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
        case 7:
        	//高于toast    低于软键盘
            return WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
        case 8:
        	//高于toast  低于软键盘
            return WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
        case 9:
        	//高于toast  高于软键盘
            return WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        case 10:
        	//高于toast  高于软键盘(键盘会把透明view顶起)
            return WindowManager.LayoutParams.TYPE_STATUS_BAR;
        case 11:
        	//高于toast  高于软键盘(键盘会把透明view顶起)
            return WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
        case 12:
        	//低于下级页面
            return WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
        case 13:
        	//is your activity running?
            return WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
        case 14:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        case 15:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_APPLICATION;
        case 16:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
        case 17:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
        case 18:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
        case 19:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
        case 20:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
        case 21:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
        case 22:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_WALLPAPER;
        case 23:
        	// is your activity running?
            return WindowManager.LayoutParams.TYPE_TOAST;
        case 24:
        	//is your activity running?
            return WindowManager.LayoutParams.TYPE_INPUT_METHOD;
        case 25:
        	//permission denied for window type 2030
            return WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
        default:
            return 0;
    }
}

参考文章

  1. Android中WindowManger的层级分析

© 版权声明
导航号,我的单页导航

暂无评论

暂无评论...