一、问题描述
由于我们的项目是手机桌面的负一屏,没有Activity而是通过Window.addView实现的。
所以无法直接使用常规的设置状态栏的方式修改颜色。
最后通过分析原理,给View设置标志位,结果还有问题,就有了这一篇文章了。
二、排查流程
一图胜千言
状态栏颜色修改不生效问题流程排查.png
- 场景
沉浸式,一个动画滚动的场景下需要吸顶,然后对应的状态栏文字需要跟着变换颜色。 - 情况特殊
由于没有Activity的存在,无法直接调用Activity的方法实现修改状态栏 - 分析状态栏修改原理 参考
其实就是给view设置标志位,与Activity并没有关系 - 分析谁调用了这个标识 Appearance_Light_Status_Bars
找到了是DisplayPolicy - 通过dump逐一排查当前状态
5.1. 肯定是appWindow,因为用的就是WindowManager.LayoutParams.TYPE_APPLICATION
5.2. attached应该为null,因为不是subWindow
5.3. 发现少了FullScreen标识,一般正常的Activity都有这个标识。但我们是负一屏,没有Activity,是通过window添加的,那么这个添加的参数是否有问题。 - 查询isFullScreen方法的判断标准
果然问题就在这里,我们原先设置的宽高直接读取了屏幕高宽,并非设置的MatchParent
三、相应的源码
DisplayPolicy
/**
* Called following layout of all window to apply policy to each window.
*
* @param win The window being positioned.
* @param attrs The LayoutParams of the window.
* @param attached For sub-windows, the window it is attached to. Otherwise null.
*/
public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
WindowState attached, WindowState imeTarget) {
//省略若干...
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type < FIRST_SYSTEM_WINDOW;
//省略若干...
// Check the windows that overlap with system bars to determine system bars' appearance.
if ((appWindow && attached == null && attrs.isFullscreen())
|| attrs.type == TYPE_VOICE_INTERACTION) {
//省略若干...
// Cache app windows that is overlapping with the status bar to determine appearance
// of status bar.
if (mStatusBar != null
&& sTmpRect.setIntersect(win.getFrame(), mStatusBar.getFrame())
&& !mStatusBarBackgroundCheckedBounds.contains(sTmpRect)) {
mStatusBarBackgroundWindows.add(win);
mStatusBarBackgroundCheckedBounds.union(sTmpRect);
if (!mStatusBarColorCheckedBounds.contains(sTmpRect)) {
mStatusBarAppearanceRegionList.add(new AppearanceRegion(
win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS,
new Rect(win.getFrame())));
mStatusBarColorCheckedBounds.union(sTmpRect);
}
}
}
//省略若干...
}
WindowManager.LayoutParams
/**
* @hide
* @return True if the layout parameters will cause the window to cover the full screen;
* false otherwise.
*/
public boolean isFullscreen() {
return x == 0 && y == 0
&& width == WindowManager.LayoutParams.MATCH_PARENT
&& height == WindowManager.LayoutParams.MATCH_PARENT;
}
网友评论