android开发浅谈之窗口管理Z

编程入门 行业动态 更新时间:2024-10-12 03:24:52

android开发<a href=https://www.elefans.com/category/jswz/34/1769825.html style=浅谈之窗口管理Z"/>

android开发浅谈之窗口管理Z

问题的描述:

软件版本为android 10.0, 测试提了一个bug,手机在不分屏时在输入法界面,toast正常显示;但是手机在分屏时,因为显示了输入法界面,toast虽然调用了,但是被输入法界面遮挡看不到。

问题分析:

那这个明显是窗口z-order管理问题,那我们先看看window的dumpsys信息:

adb shell dumpsys window windows

输入法window:

  Window #0 Window{1ac9429 u0 InputMethod}:mDisplayId=0 stackId=0 mSession=Session{805d144 3396:u0a10092} mClient=android.os.BinderProxy@7030cf3mOwnerUid=10092 mShowToOwnerOnly=true package=com.iflytek.inputmethod.custom appop=NONEmAttrs={(0,0)(fillxfill) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan} ty=INPUT_METHOD fmt=TRANSPARENT wanim=0x1030315fl=NOT_FOCUSABLE LAYOUT_IN_SCREEN SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDSvsysui=LIGHT_NAVIGATION_BAR}Requested w=1920 h=1392 mLayoutSeq=1907mIsImWindow=true mIsWallpaper=false mIsFloatingLayer=true mWallpaperVisible=falsemBaseLayer=151000 mSubLayer=0    mToken=WindowToken{36e543e android.os.Binder@de717c0}

Toast window:

  Window #8 Window{d8b3a0e u0 Toast}:mDisplayId=0 stackId=0 mSession=Session{c221ee 5661:u0a10065} mClient=android.os.BinderProxy@5e7f510mOwnerUid=10065 mShowToOwnerOnly=true package=com.royole.gallery appop=TOAST_WINDOWmAttrs={(0,144)(wrapxwrap) gr=BOTTOM CENTER sim={adjust=pan} ty=TOAST fmt=TRANSLUCENT wanim=0x1030004fl=NOT_FOCUSABLE NOT_TOUCHABLE HARDWARE_ACCELERATED}Requested w=290 h=89 mLayoutSeq=1907mBaseLayer=81000 mSubLayer=0    mToken=WindowToken{4652a4 android.os.Binder@696cd37}

我们可以看到输入法界面是排第0,mBaseLayer为151000,Toast窗口是排第8,mBaseLayer=81000。

那么我们知道窗口z-order是由mBaseLayer的值决定的,其值越大,在UI界面上越显示在前面,那输入法的mBaseLayer值大于Toast的mBaseLayer值,所以Toast必然被输入法窗口遮挡。

那我们追踪一下mBaseLayer的赋值:

WindowState.mBaseLayer其赋值计算:

WindowState.WindowState

if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {// The multiplier here is to reserve space for multiple// windows in the same type layer.mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);mIsChildWindow = true;.....
} else {// The multiplier here is to reserve space for multiple// windows in the same type layer.mBaseLayer = mPolicy.getWindowLayerLw(this)* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;mSubLayer = 0;mIsChildWindow = false;

其:

static final int TYPE_LAYER_MULTIPLIER = 10000;
static final int TYPE_LAYER_OFFSET = 1000;
mBaseLayer = mPolicy.getWindowLayerLw(this)* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;mBaseLayer = mPolicy.getWindowLayerLw(this)* 10000 + 1000;

WindowManagerPolicy.getWindowLayerLw方法为:

default int getWindowLayerLw(WindowState win) {return getWindowLayerFromTypeLw(win.getBaseType(), win.canAddInternalSystemWindow());
}default int getWindowLayerFromTypeLw(int type) {if (isSystemAlertWindowType(type)) {throw new IllegalArgumentException("Use getWindowLayerFromTypeLw() or"+ " getWindowLayerLw() for alert window types");}return getWindowLayerFromTypeLw(type, false /* canAddInternalSystemWindow */);
}default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
......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_SYSTEM_DIALOG:return  7;case TYPE_TOAST://可以看到Toast返回的值是8// toasts and the plugged-in battery thingreturn  8;case TYPE_PRIORITY_PHONE:// SIM errors and unlock.  Not sure if this really should be in a high layer.return  9;......case TYPE_INPUT_METHOD://可以看到输入法返回的值是15// on-screen keyboards and other such input method user interfaces go here.return  15;case TYPE_INPUT_METHOD_DIALOG:// on-screen keyboards and other such input method user interfaces go here.return  16;

问题解决:

那么原因我们知道了,那来吧,将Toast返回的值修改为比输入法16大的返回值,验证一下:

case TYPE_TOAST://可以看到Toast返回的值是8// toasts and the plugged-in battery thingreturn  18;

验证结果是Toast正常显示,此问题打完收工。

问题拓展:

(1)window类型的定义:

frameworks\base\core\java\android\view\WindowManager.java

application types window:

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;

sub-windows types:

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;

system-specific window types:

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;
public static final int INVALID_WINDOW_TYPE = -1;

(2)WindowManagerPolicy.getWindowLayerFromTypeLw的调用堆栈:

PhoneWindowManager.canBeHiddenByKeyguardLw–判断window是否可以被锁屏界面隐藏

WindowManagerPolicy: 	at com.android.server.policy.WindowManagerPolicy.getWindowLayerFromTypeLw(WindowManagerPolicy.java:809)
WindowManagerPolicy: 	at com.android.server.policy.WindowManagerPolicy.getWindowLayerFromTypeLw(WindowManagerPolicy.java:790)
WindowManagerPolicy: 	at com.android.server.policy.PhoneWindowManager.canBeHiddenByKeyguardLw(PhoneWindowManager.java:2661)
WindowManagerPolicy: 	at com.android.server.policy.PhoneWindowManager.applyKeyguardPolicyLw(PhoneWindowManager.java:3915)
WindowManagerPolicy: 	at com.android.server.wm.DisplayPolicy.applyPostLayoutPolicyLw(DisplayPolicy.java:2768)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.lambda$new$7$DisplayContent(DisplayContent.java:801)
WindowManagerPolicy: 	at com.android.server.wm.-$$Lambda$DisplayContent$JibsaX4YnJd0ta_wiDDdSp-PjQk.accept(Unknown Source:4)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:1189)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:1179)
WindowManagerPolicy: 	at com.android.server.wm.WindowState.applyInOrderWithImeWindows(WindowState.java:4380)
WindowManagerPolicy: 	at com.android.server.wm.WindowState.forAllWindows(WindowState.java:4279)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:888)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:888)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.forAllWindows(DisplayContent.java:2357)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:905)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.applySurfaceChangesTransaction(DisplayContent.java:3953)
WindowManagerPolicy: 	at com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction(RootWindowContainer.java:833)
WindowManagerPolicy: 	at com.android.server.wm.RootWindowContainer.performSurfacePlacementNoTrace(RootWindowContainer.java:610)
WindowManagerPolicy: 	at com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:567)
WindowManagerPolicy: 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:159)
WindowManagerPolicy: 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:105)
WindowManagerPolicy: 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:95)
WindowManagerPolicy: 	at com.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:5108)

WindowToken.canLayerAboveSystemBars–判断window是否可以显示在systembar上

WindowManagerPolicy: 	at com.android.server.policy.WindowManagerPolicy.getWindowLayerFromTypeLw(WindowManagerPolicy.java:809)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.canLayerAboveSystemBars(WindowToken.java:338)
WindowManagerPolicy: 	at com.android.server.wm.WindowState.skipDecorCrop(WindowState.java:4664)
WindowManagerPolicy: 	at com.android.server.wm.WindowState.calculatePolicyCrop(WindowState.java:4684)
WindowManagerPolicy: 	at com.android.server.wm.WindowStateAnimator.calculateCrop(WindowStateAnimator.java:797)
WindowManagerPolicy: 	at com.android.server.wm.WindowStateAnimator.setSurfaceBoundariesLocked(WindowStateAnimator.java:870)
WindowManagerPolicy: 	at com.android.server.wm.WindowStateAnimator.prepareSurfaceLocked(WindowStateAnimator.java:1095)
WindowManagerPolicy: 	at com.android.server.wm.WindowState.prepareSurfaces(WindowState.java:5095)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.prepareSurfaces(WindowContainer.java:1218)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.prepareSurfaces(WindowContainer.java:1218)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent$NonAppWindowContainers.prepareSurfaces(DisplayContent.java:5022)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.prepareSurfaces(WindowContainer.java:1218)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.prepareSurfaces(DisplayContent.java:5180)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.applySurfaceChangesTransaction(DisplayContent.java:3973)
WindowManagerPolicy: 	at com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction(RootWindowContainer.java:833)
WindowManagerPolicy: 	at com.android.server.wm.RootWindowContainer.performSurfacePlacementNoTrace(RootWindowContainer.java:610)
WindowManagerPolicy: 	at com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:567)
WindowManagerPolicy: 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:159)
WindowManagerPolicy: 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:105)
WindowManagerPolicy: 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:95)
WindowManagerPolicy: 	at com.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:5108)

DisplayContent.addWindowToken–添加windowtoken时调用

WindowManagerPolicy: 	at com.android.server.policy.WindowManagerPolicy.getWindowLayerFromTypeLw(WindowManagerPolicy.java:809)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent$NonAppWindowContainers.lambda$new$0$DisplayContent$NonAppWindowContainers(DisplayContent.java:4927)
WindowManagerPolicy: 	at com.android.server.wm.-$$Lambda$DisplayContent$NonAppWindowContainers$nqCymC3xR9b3qaeohnnJJpSiajcpare(Unknown Source:6)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:230)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent$NonAppWindowContainers.addChild(DisplayContent.java:4952)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.addWindowToken(DisplayContent.java:1078)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.reParentWindowToken(DisplayContent.java:1112)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.onDisplayChanged(WindowToken.java:263)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.<init>(WindowToken.java:124)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.<init>(WindowToken.java:110)
WindowManagerPolicy: 	at com.android.server.wm.WindowManagerService.addWindowToken(WindowManagerService.java:2608)
WindowManagerPolicy: 	at com.android.server.wm.WindowManagerService$LocalService.addWindowToken(WindowManagerService.java:7524)
WindowManagerPolicy: 	at com.android.server.notification.NotificationManagerService$10.enqueueToast(NotificationManagerService.java:2375)
WindowManagerPolicy: 	at android.app.INotificationManager$Stub.onTransact(INotificationManager.java:1114)
WindowManagerPolicy: 	at android.os.Binder.execTransactInternal(Binder.java:1021)
WindowManagerPolicy: 	at android.os.Binder.execTransact(Binder.java:994)

WindowContainer.assignChildLayers–处理子layer时调用

WindowManagerPolicy: 	at com.android.server.policy.WindowManagerPolicy.getWindowLayerFromTypeLw(WindowManagerPolicy.java:809)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent$AboveAppWindowContainers.assignChildLayers(DisplayContent.java:4899)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent$AboveAppWindowContainers.assignChildLayers(DisplayContent.java:4878)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.assignChildLayers(WindowContainer.java:1129)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.onParentChanged(WindowContainer.java:199)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.setParent(WindowContainer.java:170)
WindowManagerPolicy: 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:247)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent$NonAppWindowContainers.addChild(DisplayContent.java:4952)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.addWindowToken(DisplayContent.java:1078)
WindowManagerPolicy: 	at com.android.server.wm.DisplayContent.reParentWindowToken(DisplayContent.java:1112)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.onDisplayChanged(WindowToken.java:263)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.<init>(WindowToken.java:124)
WindowManagerPolicy: 	at com.android.server.wm.WindowToken.<init>(WindowToken.java:110)
WindowManagerPolicy: 	at com.android.server.wm.WindowManagerService.addWindowToken(WindowManagerService.java:2608)
WindowManagerPolicy: 	at com.android.server.wm.WindowManagerService$LocalService.addWindowToken(WindowManagerService.java:7524)
WindowManagerPolicy: 	at com.android.server.notification.NotificationManagerService$10.enqueueToast(NotificationManagerService.java:2375)
WindowManagerPolicy: 	at android.app.INotificationManager$Stub.onTransact(INotificationManager.java:1114)
WindowManagerPolicy: 	at android.os.Binder.execTransactInternal(Binder.java:1021)
WindowManagerPolicy: 	at android.os.Binder.execTransact(Binder.java:994)

(3)WindowState.mSubLayer–子窗口

计算方法为:
WindowState.WindowState

mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);

WindowManagerPolicy.getSubWindowLayerFromTypeLw

/*** Return how to Z-order sub-windows in relation to the window they are attached to.* Return positive to have them ordered in front, negative for behind.** @param type The sub-window type code.** @return int Layer in relation to the attached window, where positive is*         above and negative is below.*/
default int getSubWindowLayerFromTypeLw(int type) {switch (type) {case TYPE_APPLICATION_PANEL:case TYPE_APPLICATION_ATTACHED_DIALOG:return APPLICATION_PANEL_SUBLAYER;//1case TYPE_APPLICATION_MEDIA:return APPLICATION_MEDIA_SUBLAYER;//-2case TYPE_APPLICATION_MEDIA_OVERLAY:return APPLICATION_MEDIA_OVERLAY_SUBLAYER;//-1case TYPE_APPLICATION_SUB_PANEL:return APPLICATION_SUB_PANEL_SUBLAYER;//2case TYPE_APPLICATION_ABOVE_SUB_PANEL:return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;//3}Slog.e("WindowManager", "Unknown sub-window type: " + type);return 0;
}

从注解可以看出返回正数就显示在前面,返回负数就显示在后面。

WindowManagerPolicyConstants.java

int APPLICATION_LAYER = 2;
int APPLICATION_MEDIA_SUBLAYER = -2;
int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
int APPLICATION_PANEL_SUBLAYER = 1;
int APPLICATION_SUB_PANEL_SUBLAYER = 2;
int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;

更多推荐

android开发浅谈之窗口管理Z

本文发布于:2024-03-10 11:28:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1727840.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:浅谈   窗口   android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!