Skip to content

Instantly share code, notes, and snippets.

@leandro1995
Created August 13, 2025 05:09
Show Gist options
  • Save leandro1995/a898517f107c3293cfa13f7e54cb9a0d to your computer and use it in GitHub Desktop.
Save leandro1995/a898517f107c3293cfa13f7e54cb9a0d to your computer and use it in GitHub Desktop.
Archivo de utilería para cambiar los colores de los bars (statusBar y navigationBar)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
findViewById<TextView>(R.id.text).setOnClickListener {
startActivity(Intent(this, MainActivity2::class.java))
}
/**
Opcion 1
Se puede colocar desde el Activity para una modificación solo para esa ventana esto solo aplica si no lo combinan con la
segunda forma que mencionare abajo la cual es usando la extensión Application
**/
SystemBarsOnDecor.init(
window = window,
SystemBarsOnDecor.Colors(
ContextCompat.getColor(this, R.color.blue),
ContextCompat.getColor(this, R.color.black)
)
)
}
}
class Appp : Application(), Application.ActivityLifecycleCallbacks {
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(this)
}
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
/**
Opcion 2
Segunda opción es colocarlo desde el Application y de esta forma tomara del tema que tenga relacionado con su XML
recuerden que cada Activity puede tener su tema gracias a esto solo la configuración es por theme y no manual como la opción 1
**/
activity.window.decorView.post {
SystemBarsOnDecor.initFromTheme(
window = activity.window,
context = activity
)
}
}
override fun onActivityDestroyed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivitySaveInstanceState(
activity: Activity,
outState: Bundle
) {
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
}
}
@Suppress("DEPRECATION")
object SystemBarsOnDecor {
private const val STATUS_SCRIM = "statusScrim"
private const val NAV_SCRIM = "navScrim"
fun init(window: Window, colors: Colors) {
WindowCompat.setDecorFitsSystemWindows(window, false)
window.statusBarColor = Color.TRANSPARENT
window.navigationBarColor = Color.TRANSPARENT
val decor = window.decorView as ViewGroup
val statusScrim = ensureOverlay(decor, STATUS_SCRIM, Gravity.TOP)
val navScrim = ensureOverlay(decor, NAV_SCRIM, Gravity.BOTTOM)
ViewCompat.setOnApplyWindowInsetsListener(decor) { _, insets ->
val sysBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val isGestureNav = sysBars.bottom == 0
(statusScrim.layoutParams as FrameLayout.LayoutParams).apply {
width = ViewGroup.LayoutParams.MATCH_PARENT
height = sysBars.top
gravity = Gravity.TOP
}.also { statusScrim.layoutParams = it }
statusScrim.setBackgroundColor(opaque(colors.statusBar))
(navScrim.layoutParams as FrameLayout.LayoutParams).apply {
width = ViewGroup.LayoutParams.MATCH_PARENT
height = if (isGestureNav) 0 else sysBars.bottom
gravity = Gravity.BOTTOM
}.also { navScrim.layoutParams = it }
navScrim.setBackgroundColor(opaque(colors.navigationBar))
val controller = WindowInsetsControllerCompat(window, window.decorView)
controller.isAppearanceLightStatusBars = (luminance(colors.statusBar) > 0.5) && true
controller.isAppearanceLightNavigationBars =
(luminance(colors.navigationBar) > 0.5) && Build.VERSION.SDK_INT >= 26
insets
}
ViewCompat.requestApplyInsets(decor)
}
fun initFromTheme(window: Window, context: Context) {
val status = resolveInOrder(
context,
R.attr.statusBarColor,
com.google.android.material.R.attr.colorSurface,
androidx.appcompat.R.attr.colorPrimaryDark,
androidx.appcompat.R.attr.colorPrimary,
R.attr.colorBackground
)
val nav = resolveInOrder(
context,
R.attr.navigationBarColor,
com.google.android.material.R.attr.colorSurface,
androidx.appcompat.R.attr.colorBackgroundFloating,
R.attr.colorBackground
)
init(window, Colors(statusBar = status, navigationBar = nav))
}
fun updateColors(window: Window, colors: Colors) {
val decor = window.decorView as ViewGroup
val statusScrim = decor.findViewWithTag<View>(STATUS_SCRIM)
val navScrim = decor.findViewWithTag<View>(NAV_SCRIM)
statusScrim?.setBackgroundColor(opaque(colors.statusBar))
navScrim?.setBackgroundColor(opaque(colors.navigationBar))
val controller = WindowInsetsControllerCompat(window, window.decorView)
controller.isAppearanceLightStatusBars = (luminance(colors.statusBar) > 0.5) && true
controller.isAppearanceLightNavigationBars =
(luminance(colors.navigationBar) > 0.5) && Build.VERSION.SDK_INT >= 26
}
data class Colors(@ColorInt val statusBar: Int, @ColorInt val navigationBar: Int)
private fun ensureOverlay(parent: ViewGroup, tag: String, gravity: Int): View {
parent.findViewWithTag<View>(tag)?.let {
it.bringToFront()
it.elevation = 10_000f
return it
}
val overlay = View(parent.context).apply {
this.tag = tag
this.elevation = 10_000f
}
val lp = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 0, gravity
)
parent.addView(overlay, lp)
overlay.bringToFront()
return overlay
}
private fun opaque(@ColorInt c: Int) = ColorUtils.setAlphaComponent(c, 0xFF)
private fun luminance(@ColorInt c: Int) = ColorUtils.calculateLuminance(opaque(c))
@ColorInt
private fun resolveInOrder(context: Context, @AttrRes vararg attrs: Int): Int {
val tv = TypedValue()
for (attr in attrs) {
if (context.theme.resolveAttribute(attr, tv, true)) {
return if (tv.resourceId != 0) context.getColor(tv.resourceId) else tv.data
}
}
return 0xFF444444.toInt()
}
}
<!-- Recuerda que puedes generar varios temas para tu aplicación en este caso solo usare el default y uno más llamado Login. -->
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Base.Theme.Prueba5" parent="Theme.Material3.DayNight.NoActionBar">
<item name="android:statusBarColor">@color/blue</item>
<item name="android:navigationBarColor">@color/white</item>
</style>
<style name="Theme.Prueba5" parent="Base.Theme.Prueba5" />
<style name="Login" parent="Base.Theme.Prueba5">
<item name="android:statusBarColor">@color/red</item>
</style>
</resources>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment