Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b36e398d authored by Evan Laird's avatar Evan Laird
Browse files

[battery] color updates

- Allow for a separate color based on whether or not there are any
  glyphs to draw
- Update all of the colors to use a transparent bg fill
- Tweak the error state color
- Unified background colors between states
- Backgrounds are all white or black depending on the theme

Test: manual
Flag: com.android.settingslib.flags.new_status_bar_icons
Flag: com.android.systemui.status_bar_root_modernization
Bug: 400783306
Change-Id: Ic0ca9906f37755b521b15abf1569eac1f136ce6d
parent b9a00040
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.core.NewStatusBarIcons
import com.android.systemui.statusbar.events.BackgroundAnimatableView
import com.android.systemui.statusbar.pipeline.battery.domain.interactor.BatteryInteractor
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryColors.LightThemeChargingColors
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryColors
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryFrame
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryGlyph
import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryCanvas
@@ -78,7 +78,7 @@ constructor(level: Int, context: Context, attrs: AttributeSet? = null) :
                        else level.glyphRepresentation() + BatteryGlyph.Bolt,
                    level = level,
                    isFull = isFull,
                    colorsProvider = { LightThemeChargingColors },
                    colorsProvider = { BatteryColors.DarkTheme.Charging },
                )
            }
        }
+85 −39
Original line number Diff line number Diff line
@@ -17,57 +17,103 @@
package com.android.systemui.statusbar.pipeline.battery.shared.ui

import androidx.compose.ui.graphics.Color
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryColors.LightTheme.Charging
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryColors.LightTheme.Error
import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryColors.LightTheme.PowerSave

sealed interface BatteryColors {
    /** Foreground color for battery glyphs (e.g. percentage or charging bolt) */
    val glyph: Color
    /** Foreground color for the filled portion representing the level */
    val fill: Color
    val background: Color
    /**
     * Background color for when there are no glyphs. Should provide better contrast to the [fill]
     * color to improve the ability to glance at the level
     *
     * Note that the [Charging] and [PowerSave] states will always have a foreground glyph, so they
     * will not use this color.
     */
    val backgroundOnly: Color

    /** Background color suitable for providing contrast with the [glyph] color */
    val backgroundWithGlyph: Color

    /**
     * Light theme: light background, dark icons
     *
     * For color profiles that are non-default ([Charging], [Error], [PowerSave]), the foreground
     * [glyph] color is darker. This means that we want to use the low-alpha background definition
     * for the backgrounds. Using the low alpha variant will mix with a lighter background more and
     * thus allow for higher contrast with the darker [glyph] colors.
     */
    sealed class LightTheme : BatteryColors {
        override val backgroundOnly = lowAlphaBg
        override val backgroundWithGlyph = lowAlphaBg

    data object LightThemeDefaultColors : BatteryColors {
        data object Default : LightTheme() {
            override val glyph = Color.White
            override val fill = Color.Black
        override val background = Color(0xFF8C8C8C)

            /** Use a higher opacity here because the foreground is white */
            override val backgroundWithGlyph = highAlphaBg
        }

    data object LightThemeChargingColors : BatteryColors {
        override val glyph = Color(0xFF446600)
        data object Charging : LightTheme() {
            override val glyph = Color(0xFF162100)
            override val fill = Color(0xFFB4FF1E)
        override val background = Color(0xFFD6FF83)
        }

    data object LightThemeErrorColors : BatteryColors {
        override val glyph = Color(0xFF79063A)
        override val fill = Color(0xFFFF0166)
        override val background = Color(0xFFFF8CBA)
        data object Error : LightTheme() {
            override val glyph = Color(0xFF3A0907)
            override val fill = Color(0xFFFF0101)
        }

        data object PowerSave : LightTheme() {
            override val glyph = Color(0xFF2F1400)
            override val fill = Color(0xFFFFC917)
        }

    data object LightThemePowerSaveColors : BatteryColors {
        override val glyph = Color(0xFF5A4E00)
        override val fill = Color(0xFFFFDA17)
        override val background = Color(0xFFFFEB7F)
        companion object {
            private val lowAlphaBg = Color.Black.copy(alpha = 0.30f)
            private val highAlphaBg = Color.Black.copy(alpha = 0.55f)
        }
    }

    data object DarkThemeDefaultColors : BatteryColors {
    /**
     * Dark theme: dark background, light icons
     *
     * Similar to the light theme, the non-default ([Charging], [Error], [PowerSave]) colors use a
     * darker [glyph] color. But since these icons will be drawn onto darker backgrounds, we use the
     * opposite approach for the background, choosing the higher alpha variants to maximize
     * contrast.
     */
    sealed class DarkTheme : BatteryColors {
        override val backgroundOnly = lowAlphaBg
        override val backgroundWithGlyph = highAlphaBg

        data object Default : DarkTheme() {
            override val glyph = Color.Black
            override val fill = Color.White
        override val background = Color(0xFFC5C5C5)
        }

    data object DarkThemeChargingColors : BatteryColors {
        override val glyph = Color(0xFF446600)
        data object Charging : DarkTheme() {
            override val glyph = Color(0xFF162100)
            override val fill = Color(0xFFB4FF1E)
        override val background = Color(0xFFD6FF83)
        }

    data object DarkThemeErrorColors : BatteryColors {
        override val glyph = Color(0xFF79063A)
        override val fill = Color(0xFFFF0166)
        override val background = Color(0xFFFF8CBA)
        data object Error : DarkTheme() {
            override val glyph = Color(0xFF3A0907)
            override val fill = Color(0xFFFF0101)
        }

        data object PowerSave : DarkTheme() {
            override val glyph = Color(0xFF2F1400)
            override val fill = Color(0xFFFFC917)
        }

    data object DarkThemePowerSaveColors : BatteryColors {
        override val glyph = Color(0xFF5A4E00)
        override val fill = Color(0xFFFFDA17)
        override val background = Color(0xFFFFEB7F)
        companion object {
            private val lowAlphaBg = Color.White.copy(alpha = 0.45f)
            private val highAlphaBg = Color.White.copy(alpha = 0.55f)
        }
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -84,7 +84,13 @@ fun BatteryCanvas(
                drawPath(path = path.path, color = colors.fill)
            } else {
                // First draw the body
                drawPath(path.path, colors.background)
                val bgColor =
                    if (glyphs.isEmpty()) {
                        colors.backgroundOnly
                    } else {
                        colors.backgroundWithGlyph
                    }
                drawPath(path.path, bgColor)
                // Then draw the body, clipped to the fill level
                clipRect(0f, 0f, innerWidth, innerHeight) {
                    drawRoundRect(
+11 −11
Original line number Diff line number Diff line
@@ -132,24 +132,24 @@ constructor(interactor: BatteryInteractor, @Application context: Context) : Excl
                Charging,
                Defend ->
                    ColorProfile(
                        dark = BatteryColors.DarkThemeChargingColors,
                        light = BatteryColors.LightThemeChargingColors,
                        dark = BatteryColors.DarkTheme.Charging,
                        light = BatteryColors.LightTheme.Charging,
                    )
                PowerSave ->
                    ColorProfile(
                        dark = BatteryColors.DarkThemePowerSaveColors,
                        light = BatteryColors.LightThemePowerSaveColors,
                        dark = BatteryColors.DarkTheme.PowerSave,
                        light = BatteryColors.LightTheme.PowerSave,
                    )
                else ->
                    if (isCritical) {
                        ColorProfile(
                            dark = BatteryColors.DarkThemeErrorColors,
                            light = BatteryColors.LightThemeErrorColors,
                            dark = BatteryColors.DarkTheme.Error,
                            light = BatteryColors.LightTheme.Error,
                        )
                    } else {
                        ColorProfile(
                            dark = BatteryColors.DarkThemeDefaultColors,
                            light = BatteryColors.LightThemeDefaultColors,
                            dark = BatteryColors.DarkTheme.Default,
                            light = BatteryColors.LightTheme.Default,
                        )
                    }
            }
@@ -161,8 +161,8 @@ constructor(interactor: BatteryInteractor, @Application context: Context) : Excl
            traceName = "colorProfile",
            initialValue =
                ColorProfile(
                    dark = BatteryColors.DarkThemeDefaultColors,
                    light = BatteryColors.LightThemeDefaultColors,
                    dark = BatteryColors.DarkTheme.Default,
                    light = BatteryColors.LightTheme.Default,
                ),
            source = _colorProfile,
        )
@@ -256,4 +256,4 @@ constructor(interactor: BatteryInteractor, @Application context: Context) : Excl
}

/** Wrap the light and dark color into a single object so the view can decide which one it needs */
data class ColorProfile(val dark: BatteryColors, val light: BatteryColors)
data class ColorProfile(val dark: BatteryColors.DarkTheme, val light: BatteryColors.LightTheme)