一. 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
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;
(2)子窗口:
package android.view;
public interface WindowManager
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;
@UnsupportedAppUsage
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;
(3)系统窗口:
package android.view;
public interface WindowManager
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;
@Deprecated
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
@Deprecated
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;
@Deprecated
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;
@Deprecated
public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;
@Deprecated
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;
@Deprecated
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;
@UnsupportedAppUsage
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;
@UnsupportedAppUsage
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;
窗口显示顺序:
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的层级分析内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!