概述
自 Android 5.0 版本,Android 带来了沉浸式系统 bar(状态栏和导航栏),Android 的视觉效果进一步提高,各大 app 厂商也在大多数场景上使用沉浸式效果。6.0开始提供了View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR标志位,将状态栏设置为浅色模式, 清除掉这个标志, 可以恢复为深色模式.
引自:Android M如何设置状态栏图标黑白色
App调用方法
主题设置加入, 暗灰图标
<item name="android:windowLightStatusBar">true</item>
代码中实现切换
public static void changeStatusBarContrastStyle(Window window, Boolean lightIcons) {
View decorView = window.getDecorView();
if (lightIcons) {
// Draw light icons on a dark background color
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
// Draw dark icons on a light background color
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
需要更高SDK支持:
//icon color -> black
activity.getWindow().getDecorView().getWindowInsetsController().setSystemBarsAppearance(APPEARANCE_LIGHT_STATUS_BARS, APPEARANCE_LIGHT_STATUS_BARS);
//icon color -> white
activity.getWindow().getDecorView().getWindowInsetsController().setSystemBarsAppearance(0, APPEARANCE_LIGHT_STATUS_BARS);
色调变化流程
frameworks/base/core/java/android/view/View.java
@Deprecated
public void setSystemUiVisibility(int visibility) {
if (visibility != mSystemUiVisibility) {
mSystemUiVisibility = visibility;
if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
mParent.recomputeViewAttributes(this);
}
}
}
frameworks/base/core/java/android/view/ViewRootImpl.java
@Override
public void recomputeViewAttributes(View child) {
checkThread();
if (mView == child) {
mAttachInfo.mRecomputeGlobalAttributes = true;
if (!mWillDrawSoon) {
scheduleTraversals();
}
}
}
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
int updateSystemUiVisibilityLw() {
//...Ignore....
mHandler.post(() -> {
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
final int displayId = getDisplayId();
statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
cause);
if (transientState.first.length > 0) {
statusBar.showTransient(displayId, transientState.first);
}
if (transientState.second.length > 0) {
statusBar.abortTransient(displayId, transientState.second);
}
statusBar.onSystemBarAppearanceChanged(displayId, appearance,
appearanceRegions, isNavbarColorManagedByIme);
statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
// TODO(b/118118435): Remove this after removing system UI visibilities.
synchronized (mLock) {
mDisplayContent.statusBarVisibilityChanged(
visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
}
}
});
return diff;
}
SystemUI中的流程简单梳理下:
参考
Android statusbar icons color
[ANDROID] 狀態欄(STATUS BAR)文字與圖示轉換成灰色
Android 系统 Bar 沉浸式完美兼容方案
全屏、沉浸式、fitSystemWindow使用及原理分析:全方位控制“沉浸式”的实现