Android WindowManger的层级分析详解
作者:原来是图哥
这篇文章主要介绍了Android WindowManger的层级分析详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
一. Window 分类
- 应用 Window(ApplicationWindow: 对应一个 Acitivity)
- 子 Window (SubWindow:不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog 就是一个子 Window)
- 系统 Window (SystemWindow:需要声明权限才能创建的 Window,比如 Toast 和系统状态栏都是系统 Window)
二. Window层级
Window 是分层的,每个 Window 都有对应的 z-ordered,层级大的会覆盖在层级小的 Window 上面,这和 HTML 中的 z-index 概念是完全一致的。
在三种 Window 中,每一种Window的层级范围也是不同的,如下:
应用Window 1~99
子Window 1000~1999
系统Window 2000~2999
这些层级范围对应着 WindowManager.LayoutParams 的 type 参数,如果想要 Window 位于所有 Window 的最顶层,那么采用较大的层级即可,很显然系统 Window 的层级是最大的,当我们采用系统层级时,需要声明权限。
(1)应用程序窗口:
package android.view; public interface WindowManager /** * Start of window types that represent normal application windows. */ public static final int FIRST_APPLICATION_WINDOW = 1; /** * Window type: an application window that serves as the "base" window * of the overall application; all other application windows will * appear on top of it. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_BASE_APPLICATION = 1; /** * Window type: a normal application window. The {@link #token} must be * an Activity token identifying who the window belongs to. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_APPLICATION = 2; /** * Window type: special application window that is displayed while the * application is starting. Not for use by applications themselves; * this is used by the system to display something until the * application can show its own windows. * In multiuser systems shows on all users' windows. */ public static final int TYPE_APPLICATION_STARTING = 3; /** * Window type: a variation on TYPE_APPLICATION that ensures the window * manager will wait for this window to be drawn before the app is shown. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_DRAWN_APPLICATION = 4; /** * End of types of application windows. */ public static final int LAST_APPLICATION_WINDOW = 99;
(2)子窗口:
package android.view; public interface WindowManager /** * Start of types of sub-windows. The {@link #token} of these windows * must be set to the window they are attached to. These types of * windows are kept next to their attached window in Z-order, and their * coordinate space is relative to their attached window. */ public static final int FIRST_SUB_WINDOW = 1000; /** * Window type: a panel on top of an application window. These windows * appear on top of their attached window. */ public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW; /** * Window type: window for showing media (such as video). These windows * are displayed behind their attached window. */ public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1; /** * Window type: a sub-panel on top of an application window. These * windows are displayed on top their attached window and any * {@link #TYPE_APPLICATION_PANEL} panels. */ public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2; /** Window type: like {@link #TYPE_APPLICATION_PANEL}, but layout * of the window happens as that of a top-level window, <em>not</em> * as a child of its container. */ public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3; /** * Window type: window for showing overlays on top of media windows. * These windows are displayed between TYPE_APPLICATION_MEDIA and the * application window. They should be translucent to be useful. This * is a big ugly hack so: * @hide */ @UnsupportedAppUsage public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4; /** * Window type: a above sub-panel on top of an application window and it's * sub-panel windows. These windows are displayed on top of their attached window * and any {@link #TYPE_APPLICATION_SUB_PANEL} panels. * @hide */ public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5; /** * End of types of sub-windows. */ public static final int LAST_SUB_WINDOW = 1999;
(3)系统窗口:
package android.view; public interface WindowManager /** * Start of system-specific window types. These are not normally * created by applications. */ public static final int FIRST_SYSTEM_WINDOW = 2000; /** * Window type: the status bar. There can be only one status bar * window; it is placed at the top of the screen, and all other * windows are shifted down so they are below it. * In multiuser systems shows on all users' windows. */ public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW; /** * Window type: the search bar. There can be only one search bar * window; it is placed at the top of the screen. * In multiuser systems shows on all users' windows. */ public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1; /** * Window type: phone. These are non-application windows providing * user interaction with the phone (in particular incoming calls). * These windows are normally placed above all applications, but behind * the status bar. * In multiuser systems shows on all users' windows. * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead. */ @Deprecated public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2; /** * Window type: system window, such as low power alert. These windows * are always on top of application windows. * In multiuser systems shows only on the owning user's window. * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead. */ @Deprecated public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3; /** * Window type: keyguard window. * In multiuser systems shows on all users' windows. * @removed */ public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4; /** * Window type: transient notifications. * In multiuser systems shows only on the owning user's window. * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead. */ @Deprecated public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5; /** * Window type: system overlay windows, which need to be displayed * on top of everything else. These windows must not take input * focus, or they will interfere with the keyguard. * In multiuser systems shows only on the owning user's window. * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead. */ @Deprecated public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6; /** * Window type: priority phone UI, which needs to be displayed even if * the keyguard is active. These windows must not take input * focus, or they will interfere with the keyguard. * In multiuser systems shows on all users' windows. * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead. */ @Deprecated public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7; /** * Window type: panel that slides out from the status bar * In multiuser systems shows on all users' windows. */ public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8; /** * Window type: dialogs that the keyguard shows * In multiuser systems shows on all users' windows. */ public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9; /** * Window type: internal system error windows, appear on top of * everything they can. * In multiuser systems shows only on the owning user's window. * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead. */ @Deprecated public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10; /** * Window type: internal input methods windows, which appear above * the normal UI. Application windows may be resized or panned to keep * the input focus visible while this window is displayed. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11; /** * Window type: internal input methods dialog windows, which appear above * the current input method window. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12; /** * Window type: wallpaper window, placed behind any window that wants * to sit on top of the wallpaper. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13; /** * Window type: panel that slides out from over the status bar * In multiuser systems shows on all users' windows. */ public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14; /** * Window type: secure system overlay windows, which need to be displayed * on top of everything else. These windows must not take input * focus, or they will interfere with the keyguard. * * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the * system itself is allowed to create these overlays. Applications cannot * obtain permission to create secure system overlays. * * In multiuser systems shows only on the owning user's window. * @hide */ @UnsupportedAppUsage public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15; /** * Window type: the drag-and-drop pseudowindow. There is only one * drag layer (at most), and it is placed on top of all other windows. * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_DRAG = FIRST_SYSTEM_WINDOW+16; /** * Window type: panel that slides out from over the status bar * In multiuser systems shows on all users' windows. These windows * are displayed on top of the stauts bar and any {@link #TYPE_STATUS_BAR_PANEL} * windows. * @hide */ public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17; /** * Window type: (mouse) pointer * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18; /** * Window type: Navigation bar (when distinct from status bar) * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19; /** * Window type: The volume level overlay/dialog shown when the user * changes the system volume. * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20; /** * Window type: The boot progress dialog, goes on top of everything * in the world. * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21; /** * Window type to consume input events when the systemUI bars are hidden. * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22; /** * Window type: Dreams (screen saver) window, just above keyguard. * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23; /** * Window type: Navigation bar panel (when navigation bar is distinct from status bar) * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24; /** * Window type: Display overlay window. Used to simulate secondary display devices. * In multiuser systems shows on all users' windows. * @hide */ @UnsupportedAppUsage public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26; /** * Window type: Magnification overlay window. Used to highlight the magnified * portion of a display when accessibility magnification is enabled. * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27; /** * Window type: Window for Presentation on top of private * virtual display. */ public static final int TYPE_PRIVATE_PRESENTATION = FIRST_SYSTEM_WINDOW+30; /** * Window type: Windows in the voice interaction layer. * @hide */ public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31; /** * Window type: Windows that are overlaid <em>only</em> by a connected {@link * android.accessibilityservice.AccessibilityService} for interception of * user interactions without changing the windows an accessibility service * can introspect. In particular, an accessibility service can introspect * only windows that a sighted user can interact with which is they can touch * these windows or can type into these windows. For example, if there * is a full screen accessibility overlay that is touchable, the windows * below it will be introspectable by an accessibility service even though * they are covered by a touchable window. */ public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32; /** * Window type: Starting window for voice interaction layer. * @hide */ public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33; /** * Window for displaying a handle used for resizing docked stacks. This window is owned * by the system process. * @hide */ public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34; /** * Window type: like {@link #TYPE_APPLICATION_ATTACHED_DIALOG}, but used * by Quick Settings Tiles. * @hide */ public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35; /** * Window type: shares similar characteristics with {@link #TYPE_DREAM}. The layer is * reserved for screenshot region selection. These windows must not take input focus. * @hide */ public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36; /** * Window type: Window for Presentation on an external display. * @see android.app.Presentation * @hide */ public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37; /** * Window type: Application overlay windows are displayed above all activity windows * (types between {@link #FIRST_APPLICATION_WINDOW} and {@link #LAST_APPLICATION_WINDOW}) * but below critical system windows like the status bar or IME. * <p> * The system may change the position, size, or visibility of these windows at anytime * to reduce visual clutter to the user and also manage resources. * <p> * Requires {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission. * <p> * The system will adjust the importance of processes with this window type to reduce the * chance of the low-memory-killer killing them. * <p> * In multi-user systems shows only on the owning user's screen. */ public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38; /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999;
窗口显示顺序:
Type 值越大层级越高,Type 值大的覆盖 Type 值小的,这只是一般规律。
(三)如何真正查看 Window 的优先级
/frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java 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; } }
以上返回的是除 Application 外的 Window 的层级,在开发系统应用时可以选择一种开发自己的 Window.
(四) 层级高低具体分析(对比Toast以及软键盘)
低于toast--->盖不住toast 低于软键盘--->盖不住软键盘 依附Activity使用--->is your activity running? public static int getWindowType(int num) { switch (num) { case 1: return WindowManager.LayoutParams.TYPE_PHONE;//低于toast 低于软键盘 case 2: return WindowManager.LayoutParams.TYPE_SEARCH_BAR;//低于toast 低于软键盘 case 3: return WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;//低于toast 低于软键盘 case 4: return WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;//高于toast 低于软键盘 case 5: return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;//高于toast 低于软键盘 case 6: return WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;//高于toast 盖住键盘 case 7: return WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;//高于toast 低于软键盘 case 8: return WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;//高于toast 低于软键盘 case 9: return WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;//高于toast 高于软键盘 case 10: return WindowManager.LayoutParams.TYPE_STATUS_BAR;//高于toast 高于软键盘(键盘会把透明view顶起) case 11: return WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;//高于toast 高于软键盘(键盘会把透明view顶起) case 12: return WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;//低于下级页面 case 13: return WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;//is your activity running? case 14: return WindowManager.LayoutParams.TYPE_BASE_APPLICATION;// is your activity running? case 15: return WindowManager.LayoutParams.TYPE_APPLICATION;// is your activity running? case 16: return WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;// is your activity running? case 17: return WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;// is your activity running? case 18: return WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;// is your activity running? case 19: return WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;// is your activity running? case 20: return WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;// is your activity running? case 21: return WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;// is your activity running? case 22: return WindowManager.LayoutParams.TYPE_WALLPAPER;// is your activity running? case 23: return WindowManager.LayoutParams.TYPE_TOAST;// is your activity running? case 24: return WindowManager.LayoutParams.TYPE_INPUT_METHOD;//is your activity running? case 25: return WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;//permission denied for window type 2030 default: return 0; } }
(五)如何定制系统层级
改变层级关系需要改写 getWindowLayerFromTypeLw 的 switch 顺序结构和返回值
如果需要更改一些 Window 的行为,需要修改
/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
到此这篇关于Android WindowManger的层级分析详解的文章就介绍到这了,更多相关Android WindowManger的层级分析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!