Created
August 13, 2025 05:09
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
) | |
) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) { | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- 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