In my case, my activity content was complex, so accessing it through Custom-Theme method was not suitable. @Shouheng Wang's suggestion was the best, but his suggestion needs some modifications. First, I changed it to Kotlin code. And 'resources.getIdentifier' is slow/heavy and is not recommended. My suggestions for improvement are as follows:
Step 1.
Create a 'BarUtils.kt' file. And fill in the following code:
object BarUtils {
private const val TAG_STATUS_BAR = "TAG_STATUS_BAR"
// for Lollipop (SDK 21+)
fun transparentStatusBar(window: Window) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
val option =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
val vis = window.decorView.systemUiVisibility
window.decorView.systemUiVisibility = option or vis
window.statusBarColor = Color.TRANSPARENT
}
fun applyStatusBarColor (window: Window, color: Int, isDecor: Boolean, getStatusBarHeight: Int): View {
val parent = if (isDecor) window.decorView as ViewGroup else (window.findViewById<View>(R.id.content) as ViewGroup)
var fakeStatusBarView = parent.findViewWithTag<View>(TAG_STATUS_BAR)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(color)
} else {
fakeStatusBarView = **createStatusBarView** (window, color, getStatusBarHeight)
parent.addView(fakeStatusBarView)
}
return fakeStatusBarView
}
private fun createStatusBarView (window: Window, color: Int, **getStatusBarHeight**: Int): View {
val statusBarView = View(window.context)
statusBarView.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, **getStatusBarHeight**
)
statusBarView.setBackgroundColor(color)
statusBarView.tag = TAG_STATUS_BAR
return statusBarView
}
}
Step 2:
Then, insert the following code into the Activity to get getStatusBarHeight, which is the height of the Status Bar.
if (Build.VERSION.SDK_INT >= 24) {
enableEdgeToEdge()
ViewCompat.setOnApplyWindowInsetsListener(maBinding.root) { v, windowInsets ->
val currentNightMode = (resources.configuration.uiMode
and Configuration.UI_MODE_NIGHT_MASK)
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars())
v.run {
updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
when (currentNightMode) {
Configuration.UI_MODE_NIGHT_NO -> {
BarUtils.applyStatusBarColor(window, Color.WHITE,true, topMargin)
}
Configuration.UI_MODE_NIGHT_YES -> {
BarUtils.applyStatusBarColor(window, Color.BLACK,true, topMargin)
}
Configuration.UI_MODE_NIGHT_UNDEFINED -> {
BarUtils.applyStatusBarColor(window, Color.WHITE,true, topMargin)
}
}
}
}
windowInsets
//WindowInsetsCompat.CONSUMED
}
} else {
BarUtils.transparentStatusBar(window)
}
note:
If you forget enableEdgeToEdge(), the StatusBar color will not appear correctly.
A crash occurs if it is located before the activity's setContentView().
If you do not use v.run {}, 'ViewCompat' changes the height of the activity StatusBar. Don't forget that this code only retrieves the value of 'getStatusBarHeight'. (For the same reason, 'windowInsets' was used instead of 'WindowInsetsCompat.CONSUMED'.)
The 'currentNightMode' part is for dark mode.