概述
问题的描述:
软件版本为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@7030cf3
mOwnerUid=10092 mShowToOwnerOnly=true package=com.iflytek.inputmethod.custom appop=NONE
mAttrs={(0,0)(fillxfill) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan} ty=INPUT_METHOD fmt=TRANSPARENT wanim=0x1030315
fl=NOT_FOCUSABLE LAYOUT_IN_SCREEN SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
vsysui=LIGHT_NAVIGATION_BAR}
Requested w=1920 h=1392 mLayoutSeq=1907
mIsImWindow=true mIsWallpaper=false mIsFloatingLayer=true mWallpaperVisible=false
mBaseLayer=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@5e7f510
mOwnerUid=10065 mShowToOwnerOnly=true package=com.royole.gallery appop=TOAST_WINDOW
mAttrs={(0,144)(wrapxwrap) gr=BOTTOM CENTER sim={adjust=pan} ty=TOAST fmt=TRANSLUCENT wanim=0x1030004
fl=NOT_FOCUSABLE NOT_TOUCHABLE HARDWARE_ACCELERATED}
Requested w=290 h=89 mLayoutSeq=1907
mBaseLayer=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 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_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 thing
return
18;
验证结果是Toast正常显示,此问题打完收工。
问题拓展:
(1)window类型的定义:
frameworksbasecorejavaandroidviewWindowManager.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$nqCymC3xR9b3qaeohnnJJpSiajc.compare(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;//1
case TYPE_APPLICATION_MEDIA:
return APPLICATION_MEDIA_SUBLAYER;//-2
case TYPE_APPLICATION_MEDIA_OVERLAY:
return APPLICATION_MEDIA_OVERLAY_SUBLAYER;//-1
case TYPE_APPLICATION_SUB_PANEL:
return APPLICATION_SUB_PANEL_SUBLAYER;//2
case 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-Order问题的描述:问题分析:问题解决:问题拓展:的全部内容,希望文章能够帮你解决android开发浅谈之窗口管理Z-Order问题的描述:问题分析:问题解决:问题拓展:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复