设置状态栏文字颜色(黑/白)
设置为浅色状态栏,即黑色字体
private fun setLightStatusBar() {
val flags = window.decorView.systemUiVisibility
window.decorView.systemUiVisibility = flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
设置为深色状态栏,即白色字体
private fun setDarkStatusBar() {
val flags = window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
window.decorView.systemUiVisibility = flags xor View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
根据页面前景颜色动态改变状态栏图标颜色
Google提供了一个专门用于图像颜色提取和识别的库(Palette)。使用步骤:
1、引入依赖
dependencies {
implementation 'androidx.palette:palette:1.0.0'
}
2、基本用法
val colorCount = 20
val left = 0
val top = 0
val right = getScreenWidth()
val bottom = getStatusBarHeight()
Palette
.from(bitmap)
.setRegion(left, top, right, bottom)
.maximumColorCount(colorCount)
.generate {
it?.let { palette ->
var mostPopularSwatch: Palette.Swatch? = null
for (swatch in palette.swatches) {
if (mostPopularSwatch == null
|| swatch.population > mostPopularSwatch.population
) {
mostPopularSwatch = swatch
}
}
mostPopularSwatch?.let { swatch ->
val luminance = ColorUtils.calculateLuminance(swatch.rgb)
// If the luminance value is lower than 0.5, we consider it as dark.
if (luminance < 0.5) {
setDarkStatusBar()
} else {
setLightStatusBar()
}
}
}
}
- from:方法需传一张bitmap图片,即Palette要解析的对象
- setRegion:方法传入4个参数用于指定需要提取和解析的图像区域
- maximumColorCount:告诉Palette一共需要提取多少个颜色特征点
- generate:方法开始解析并将结果返回lambda表达式中
获取状态的宽度和高度
private fun getScreenWidth(): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
windowManager.currentWindowMetrics.bounds.right
} else {
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
displayMetrics.widthPixels
}
}
private fun getStatusBarHeight(): Int {
var result = 0
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
沉浸式状态栏
所谓沉浸式状态栏就是将页面内容延伸到状态栏顶部,这样视觉效果更好, 我们需要在布局的根view添加”android:fitsSystemWindows”属性,同时我们的根布局必须使用”androidx.coordinatorlayout.widget.CoordinatorLayout” 控件。
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
</androidx.coordinatorlayout.widget.CoordinatorLayout>
CoordinatorLayout的内部会根据fitsSystemWindows属性设置
setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
这样CoordinatorLayout布局就能全屏显示了, 被CoordinatorLayout包含的子控件会自动偏移到状态栏一下, 如果我们需要子控件延伸到状态栏里面,需要将子控件用com.google.android.material.appbar.CollapsingToolbarLayout布局包含起来。
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ImageView
android:id="@+id/bg_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
...
</androidx.coordinatorlayout.widget.CoordinatorLayout>
隐藏底部导航栏,上滑显示
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Android R及以上使用windowInsetsController来控制状态栏和导航栏的状态,需要引用"androidx.core:core:1.5.0"及以上的依赖库
val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView)
windowInsetsController?.hide(WindowInsetsCompat.Type.navigationBars())
windowInsetsController?.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} else {
// R以下设置systemUiVisibility value
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
}