一、簡(jiǎn)要說(shuō)明
頂部的有時(shí)間手機(jī)電量展示的叫做 狀態(tài)欄
底部的有三個(gè)虛擬按鍵的叫做導(dǎo)航欄
注意以下討論,基于Android版本11,也就是沒啥版本兼容的考慮
一般都是為了實(shí)現(xiàn)沉浸式的效果
二、一般做法
對(duì)于大多數(shù)的App頁(yè)面來(lái)說(shuō)都是需要沉浸式的。
所以就在Activity上要設(shè)置
WindowCompat.setDecorFitsSystemWindows(window, false)
然后設(shè)置這個(gè)后,內(nèi)容區(qū)域就會(huì)擴(kuò)展到整個(gè)狀態(tài)欄。
一般狀態(tài)欄的背景色要設(shè)置成透明的,否則兩種顏色疊加在一起不好看。
<item name="android:statusBarColor">@android:color/transparent</item>
接著就需要注意是否會(huì)有重疊的情況,也就是頂部是否需要預(yù)留狀態(tài)欄的高度,避免不好看
高度都是不一樣的,這里可以去讀取高度
context.getResources().getIdentifier("status_bar_height", "dimen", "android");
再接著就是有可能你的內(nèi)容背景色與狀態(tài)欄文字顏色不搭,導(dǎo)致看不清楚
這時(shí)候就需要設(shè)置狀態(tài)欄文字顏色
修改狀態(tài)欄為暗色風(fēng)格,則文字為亮色
<item name="android:windowLightStatusBar">false</item>
1 最終在Activity的主題中
<style name="SampleTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
//修改狀態(tài)欄為透明
<item name="android:statusBarColor">@android:color/transparent</item>
//修改狀態(tài)欄為暗色風(fēng)格,則文字為亮色
<item name="android:windowLightStatusBar">false</item>
//修改導(dǎo)航欄為非半透明
<item name="android:windowTranslucentNavigation">false</item>
//修改導(dǎo)航欄為透明
<item name="android:navigationBarColor">@android:color/transparent</item>
//修改導(dǎo)航欄忽略對(duì)比度不夠的問題
<item name="android:enforceNavigationBarContrast">false</item>
</style>
2 在Compose中可以這么寫
有一個(gè)庫(kù),可以實(shí)現(xiàn)
ProvideWindowInsets {
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = statusDarkIcons)
systemUiController.setNavigationBarColor(
navigationBarColor,
darkIcons = navigationDarkIcons,
navigationBarContrastEnforced = false
)
}
content()
}
SystemUiController.setStatusBarColor原理
重點(diǎn)看注釋即可
SystemUiController.kt
//rememberSystemUiController實(shí)現(xiàn)類是 AndroidSystemUiController
override fun setStatusBarColor(
color: Color,
darkIcons: Boolean,
transformColorForLightContent: (Color) -> Color
) {
//這個(gè)則最終調(diào)用的是WindowInsetControllerCompat
statusBarDarkContentEnabled = darkIcons
// 這里調(diào)用的是 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) {
// 這個(gè)標(biāo)識(shí)說(shuō)是被廢棄了
setSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
//重點(diǎn)是這個(gè)標(biāo)識(shí)
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);
}
}