Android状态栏设置背景色
2022-12-15 本文已影响0人
艾伦宇
一、简要说明
顶部的有时间手机电量展示的叫做 状态栏
底部的有三个虚拟按键的叫做导航栏
注意以下讨论,基于Android版本11,也就是没啥版本兼容的考虑
一般都是为了实现沉浸式的效果
二、一般做法
对于大多数的App页面来说都是需要沉浸式的。
所以就在Activity上要设置
WindowCompat.setDecorFitsSystemWindows(window, false)
然后设置这个后,内容区域就会扩展到整个状态栏。
一般状态栏的背景色要设置成透明的,否则两种颜色叠加在一起不好看。
<item name="android:statusBarColor">@android:color/transparent</item>
接着就需要注意是否会有重叠的情况,也就是顶部是否需要预留状态栏的高度,避免不好看
高度都是不一样的,这里可以去读取高度
context.getResources().getIdentifier("status_bar_height", "dimen", "android");
再接着就是有可能你的内容背景色与状态栏文字颜色不搭,导致看不清楚
这时候就需要设置状态栏文字颜色
修改状态栏为暗色风格,则文字为亮色
<item name="android:windowLightStatusBar">false</item>
1 最终在Activity的主题中
<style name="SampleTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
//修改状态栏为透明
<item name="android:statusBarColor">@android:color/transparent</item>
//修改状态栏为暗色风格,则文字为亮色
<item name="android:windowLightStatusBar">false</item>
//修改导航栏为非半透明
<item name="android:windowTranslucentNavigation">false</item>
//修改导航栏为透明
<item name="android:navigationBarColor">@android:color/transparent</item>
//修改导航栏忽略对比度不够的问题
<item name="android:enforceNavigationBarContrast">false</item>
</style>
2 在Compose中可以这么写
有一个库,可以实现
ProvideWindowInsets {
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = statusDarkIcons)
systemUiController.setNavigationBarColor(
navigationBarColor,
darkIcons = navigationDarkIcons,
navigationBarContrastEnforced = false
)
}
content()
}
SystemUiController.setStatusBarColor原理
重点看注释即可
SystemUiController.kt
//rememberSystemUiController实现类是 AndroidSystemUiController
override fun setStatusBarColor(
color: Color,
darkIcons: Boolean,
transformColorForLightContent: (Color) -> Color
) {
//这个则最终调用的是WindowInsetControllerCompat
statusBarDarkContentEnabled = darkIcons
// 这里调用的是 PhoneWindow.setStatusBarColor
window?.statusBarColor = when {
darkIcons && !windowInsetsController.isAppearanceLightStatusBars -> {
// If we're set to use dark icons, but our windowInsetsController call didn't
// succeed (usually due to API level), we instead transform the color to maintain
// contrast
transformColorForLightContent(color)
}
else -> color
}.toArgb()
}
override var statusBarDarkContentEnabled: Boolean
get() = windowInsetsController.isAppearanceLightStatusBars
set(value) {
windowInsetsController.isAppearanceLightStatusBars = value
}
WindowInsetControllerCompat.java
@Override
public void setAppearanceLightStatusBars(boolean isLight) {
if (isLight) {
if (mWindow != null) {
// 这个标识说是被废弃了
setSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
//重点是这个标识
mInsetsController.setSystemBarsAppearance(
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS,
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
} else {
if (mWindow != null) {
unsetSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
mInsetsController.setSystemBarsAppearance(
0,
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
}
}
PhoneWindow.java
public void setStatusBarColor(int color) {
mStatusBarColor = color;
mForcedStatusBarColor = true;
if (mDecor != null) {
mDecor.updateColorViews(null, false /* animate */);
}
final WindowControllerCallback callback = getWindowControllerCallback();
if (callback != null) {
getWindowControllerCallback().updateStatusBarColor(color);
}
}