Adjust weather icons color

This commit is contained in:
MM20
2026-02-17 18:40:26 +01:00
parent adfff23e67
commit f89d8135b1
4 changed files with 105 additions and 163 deletions

View File

@@ -189,21 +189,20 @@ private fun Cloud1(icon: WeatherIcon, colors: WeatherIconColors) {
when (it) {
WeatherIcon.Thunderstorm,
WeatherIcon.Thunder,
WeatherIcon.Wind -> colors.cloudDark2
WeatherIcon.Wind,
WeatherIcon.HeavyRain -> colors.cloud1
WeatherIcon.Rain,
WeatherIcon.HeavyRain,
WeatherIcon.Sleet,
WeatherIcon.Hail,
WeatherIcon.Overcast,
WeatherIcon.Wind,
WeatherIcon.Fog -> colors.cloudDark1
WeatherIcon.Fog -> colors.cloud2
WeatherIcon.LightRain,
WeatherIcon.Snow -> colors.cloudMedium2
WeatherIcon.Snow -> colors.cloud3
WeatherIcon.PartlyCloudy -> colors.cloudLight1
else -> colors.cloudMedium2
WeatherIcon.PartlyCloudy -> colors.cloud5
else -> colors.cloud3
}
}
@@ -261,19 +260,19 @@ private fun Cloud2(icon: WeatherIcon, colors: WeatherIconColors) {
when (it) {
WeatherIcon.Thunderstorm,
WeatherIcon.Thunder,
WeatherIcon.Wind -> colors.cloudMedium2
WeatherIcon.Wind,
WeatherIcon.HeavyRain -> colors.cloud2
WeatherIcon.Rain,
WeatherIcon.HeavyRain,
WeatherIcon.LightRain,
WeatherIcon.Sleet,
WeatherIcon.Snow,
WeatherIcon.Hail,
WeatherIcon.Overcast,
WeatherIcon.Wind,
WeatherIcon.Fog -> colors.cloudMedium1
WeatherIcon.Fog -> colors.cloud3
else -> colors.cloudMedium2
WeatherIcon.LightRain,
WeatherIcon.Snow -> colors.cloud4
else -> colors.cloud2
}
}
@@ -329,19 +328,18 @@ private fun Cloud3(icon: WeatherIcon, colors: WeatherIconColors) {
when (it) {
WeatherIcon.Thunderstorm,
WeatherIcon.Thunder,
WeatherIcon.Wind -> colors.cloudDark1
WeatherIcon.Wind,
WeatherIcon.HeavyRain -> colors.cloud3
WeatherIcon.Rain,
WeatherIcon.HeavyRain,
WeatherIcon.Sleet,
WeatherIcon.Hail,
WeatherIcon.Overcast,
WeatherIcon.Wind -> colors.cloudMedium2
WeatherIcon.Overcast -> colors.cloud4
WeatherIcon.LightRain,
WeatherIcon.Snow -> colors.cloudLight2
WeatherIcon.Snow -> colors.cloud5
else -> colors.cloudMedium2
else -> colors.cloud4
}
}
@@ -429,8 +427,8 @@ fun AnimatedWeatherIconTestPanel() {
AnimatedWeatherIcon(icon = icon, night = night)
WeatherIcon(icon = icon, night = night)
val monochromeColors = WeatherIconDefaults.monochromeColors(
MaterialTheme.colorScheme.secondary
val monochromeColors = WeatherIconDefaults.themedColors(
MaterialTheme.colorScheme.secondary,
)
AnimatedWeatherIcon(

View File

@@ -123,19 +123,19 @@ private fun Cloud1(icon: WeatherIcon, colors: WeatherIconColors) {
}
val color = when (icon) {
WeatherIcon.Thunderstorm,
WeatherIcon.Thunder -> colors.cloudDark2
WeatherIcon.Thunder,
WeatherIcon.HeavyRain -> colors.cloud1
WeatherIcon.Rain,
WeatherIcon.HeavyRain,
WeatherIcon.Sleet,
WeatherIcon.Hail,
WeatherIcon.Overcast,
WeatherIcon.Fog -> colors.cloudDark1
WeatherIcon.Fog -> colors.cloud2
WeatherIcon.LightRain,
WeatherIcon.Snow -> colors.cloudMedium2
WeatherIcon.Snow -> colors.cloud3
WeatherIcon.PartlyCloudy -> colors.cloudLight1
WeatherIcon.PartlyCloudy -> colors.cloud5
}
Icon(
@@ -195,16 +195,17 @@ private fun Cloud2(icon: WeatherIcon, colors: WeatherIconColors) {
}
val color = when (icon) {
WeatherIcon.Thunderstorm,
WeatherIcon.Thunder -> colors.cloudMedium2
WeatherIcon.Thunder,
WeatherIcon.HeavyRain -> colors.cloud2
WeatherIcon.Rain,
WeatherIcon.HeavyRain,
WeatherIcon.LightRain,
WeatherIcon.Sleet,
WeatherIcon.Snow,
WeatherIcon.Hail,
WeatherIcon.Overcast,
WeatherIcon.Fog -> colors.cloudMedium1
WeatherIcon.Fog -> colors.cloud3
WeatherIcon.LightRain,
WeatherIcon.Snow -> colors.cloud4
}
Icon(
@@ -246,16 +247,16 @@ private fun Cloud3(icon: WeatherIcon, colors: WeatherIconColors) {
}
val color = when (icon) {
WeatherIcon.Thunderstorm,
WeatherIcon.Thunder -> colors.cloudDark1
WeatherIcon.Thunder,
WeatherIcon.HeavyRain -> colors.cloud3
WeatherIcon.Rain,
WeatherIcon.HeavyRain,
WeatherIcon.Sleet,
WeatherIcon.Hail,
WeatherIcon.Overcast -> colors.cloudMedium2
WeatherIcon.Overcast -> colors.cloud4
WeatherIcon.LightRain,
WeatherIcon.Snow -> colors.cloudLight2
WeatherIcon.Snow -> colors.cloud5
}
Icon(

View File

@@ -9,162 +9,100 @@ import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import blend.Blend
import de.mm20.launcher2.ui.ktx.atTone
import de.mm20.launcher2.ui.locals.LocalDarkTheme
import hct.Hct
data class WeatherIconColors(
val sun: Color,
val moon: Color,
val cloudDark1: Color,
val cloudDark2: Color,
val cloudMedium1: Color,
val cloudMedium2: Color,
val cloudLight1: Color,
val cloudLight2: Color,
val cloud1: Color,
val cloud2: Color,
val cloud3: Color,
val cloud4: Color,
val cloud5: Color,
val rain: Color,
val snow: Color,
val hail: Color,
val fog: Color,
val wind: Color,
val windDark: Color,
val lightningBolt: Color,
val hot: Color,
val cold: Color,
)
object WeatherIconDefaults {
@Composable
fun colors(): WeatherIconColors {
val darkTheme = LocalDarkTheme.current
if (darkTheme) {
return darkColors()
} else {
return lightColors()
@Composable
fun colors(
background: Color = MaterialTheme.colorScheme.surface
): WeatherIconColors {
val themeColor = MaterialTheme.colorScheme.primary
val neutralColor = MaterialTheme.colorScheme.outline
return remember(background, neutralColor, themeColor) {
val baseTone = Hct.fromInt(background.toArgb()).tone.toInt()
WeatherIconColors(
sun = harmonize(0xfff7ae00.toInt(), themeColor).atTone(t(baseTone, 75)),
moon = neutralColor.atTone(t(baseTone, 90)),
cloud1 = neutralColor.atTone(t(baseTone, 20)),
cloud2 = neutralColor.atTone(t(baseTone, 35)),
cloud3 = neutralColor.atTone(t(baseTone, 50)),
cloud4 = neutralColor.atTone(t(baseTone, 65)),
cloud5 = neutralColor.atTone(t(baseTone, 90)),
rain = harmonize(0xff1c71d8.toInt(), themeColor).atTone(t(baseTone, 50)),
snow = neutralColor.atTone(t(baseTone, 100)),
hail = neutralColor.atTone(t(baseTone, 90)),
fog = neutralColor.atTone(t(baseTone, 60)),
wind = neutralColor.atTone(t(baseTone, 65)),
lightningBolt = harmonize(0xfff7ae00.toInt(), themeColor).atTone(t(baseTone, 80)),
hot = harmonize(0xffec3435.toInt(), themeColor).atTone(t(baseTone, 50)),
cold = harmonize(0xff1c71d8.toInt(), themeColor).atTone(t(baseTone, 50)),
)
}
}
@Composable
fun invertedColors(): WeatherIconColors {
val darkTheme = LocalDarkTheme.current
if (!darkTheme) {
return darkColors()
} else {
return lightColors()
}
}
@Composable
fun darkColors(): WeatherIconColors {
val context = LocalContext.current
fun themedColors(backgroundColor: Color): WeatherIconColors {
val themeColor = MaterialTheme.colorScheme.primary
val neutralColor = MaterialTheme.colorScheme.outline
val neutral1 = MaterialTheme.colorScheme.outline
val neutral2 = MaterialTheme.colorScheme.outline
return remember(backgroundColor, themeColor, neutralColor) {
val baseTone = Hct.fromInt(backgroundColor.toArgb()).tone.toInt()
return remember(themeColor) {
WeatherIconColors(
sun = harmonize(0xFFFFB300.toInt(), themeColor),
moon = harmonize(0xFF9E9E9E.toInt(), themeColor),
cloudDark1 = harmonize(neutral1.atTone(40).toArgb(), themeColor),
cloudDark2 = harmonize(neutral1.atTone(30).toArgb(), themeColor),
cloudMedium1 = harmonize(neutral1.atTone(60).toArgb(), themeColor),
cloudMedium2 = harmonize(neutral1.atTone(50).toArgb(), themeColor),
cloudLight1 = harmonize(neutral1.atTone(95).toArgb(), themeColor),
cloudLight2 = harmonize(neutral1.atTone(85).toArgb(), themeColor),
rain = harmonize(0xFF64B5F6.toInt(), themeColor),
snow = harmonize(0xFFF5F5F5.toInt(), themeColor),
hail = harmonize(0xFFF5F5F5.toInt(), themeColor),
fog = harmonize(neutral1.atTone(95).toArgb(), themeColor),
wind = harmonize(neutral2.atTone(70).toArgb(), themeColor),
windDark = harmonize(neutral2.atTone(40).toArgb(), themeColor),
lightningBolt = harmonize(0xFFFFB300.toInt(), themeColor),
hot = harmonize(0xFFE57373.toInt(), themeColor),
cold = harmonize(0xFF4FC3F7.toInt(), themeColor),
sun = themeColor.atTone(t(baseTone, 75)),
moon = neutralColor.atTone(t(baseTone, 90)),
cloud1 = neutralColor.atTone(t(baseTone, 20)),
cloud2 = neutralColor.atTone(t(baseTone, 35)),
cloud3 = neutralColor.atTone(t(baseTone, 50)),
cloud4 = neutralColor.atTone(t(baseTone, 65)),
cloud5 = neutralColor.atTone(t(baseTone, 90)),
rain = themeColor.atTone(t(baseTone, 55)),
snow = neutralColor.atTone(t(baseTone, 100)),
hail = neutralColor.atTone(t(baseTone, 90)),
fog = neutralColor.atTone(t(baseTone, 60)),
wind = neutralColor.atTone(t(baseTone, 65)),
lightningBolt = themeColor.atTone(t(baseTone, 80)),
hot = themeColor.atTone(t(baseTone, 50)),
cold = themeColor.atTone(t(baseTone, 50)),
)
}
}
@Composable
fun lightColors(): WeatherIconColors {
val context = LocalContext.current
private fun t(base: Int, tone: Int): Int {
val upper = (base + 15f).coerceAtMost(100f)
val lower = (base - 15f).coerceAtLeast(0f)
val diff = upper - lower
val scale = (100f - diff) / 100f
val themeColor = MaterialTheme.colorScheme.primary
val neutral1 = MaterialTheme.colorScheme.outline
val neutral2 = MaterialTheme.colorScheme.outline
val tn = tone * scale
return remember(themeColor) {
WeatherIconColors(
sun = harmonize(0xFFFFB300.toInt(), themeColor),
moon = harmonize(0xFF9E9E9E.toInt(), themeColor),
cloudDark1 = harmonize(neutral1.atTone(30).toArgb(), themeColor),
cloudDark2 = harmonize(neutral1.atTone(20).toArgb(), themeColor),
cloudMedium1 = harmonize(neutral1.atTone(50).toArgb(), themeColor),
cloudMedium2 = harmonize(neutral1.atTone(40).toArgb(), themeColor),
cloudLight1 = harmonize(neutral1.atTone(85).toArgb(), themeColor),
cloudLight2 = harmonize(neutral1.atTone(75).toArgb(), themeColor),
rain = harmonize(0xFF1E88E5.toInt(), themeColor),
snow = harmonize(0xFFE0E0E0.toInt(), themeColor),
hail = harmonize(0xFFE0E0E0.toInt(), themeColor),
fog = harmonize(neutral1.atTone(85).toArgb(), themeColor),
wind = harmonize(neutral2.atTone(75).toArgb(), themeColor),
windDark = harmonize(neutral2.atTone(45).toArgb(), themeColor),
lightningBolt = harmonize(0xFFFFB300.toInt(), themeColor),
hot = harmonize(0xFFE53935.toInt(), themeColor),
cold = harmonize(0xFF039BE5.toInt(), themeColor),
)
}
}
@Composable
fun monochromeColors(baseColor: Color): WeatherIconColors {
val baseTone = Hct.fromInt(baseColor.toArgb()).tone.toInt()
return remember(baseColor) {
/**
* Adjusts the tone of a color.
* The tone is adjusted up or down to not overlap with the base color's tone.
*
* @param tone The tone to adjust.
* @return The adjusted tone.
*/
fun t(tone: Int): Int {
val upper = (baseTone + 15f).coerceAtMost(100f)
val lower = (baseTone - 15f).coerceAtLeast(0f)
val diff = upper - lower
val scale = (100f - diff) / 100f
val tn = tone * scale
if (tn > lower) {
return (tn + diff).toInt()
}
return tn.toInt()
}
WeatherIconColors(
sun = baseColor.atTone(t(90)),
moon = baseColor.atTone(t(90)),
cloudDark1 = baseColor.atTone(t(25)),
cloudDark2 = baseColor.atTone(t(15)),
cloudMedium1 = baseColor.atTone(t(45)),
cloudMedium2 = baseColor.atTone(t(35)),
cloudLight1 = baseColor.atTone(t(65)),
cloudLight2 = baseColor.atTone(t(55)),
rain = baseColor.atTone(t(55)),
snow = baseColor.atTone(t(100)),
hail = baseColor.atTone(t(90)),
fog = baseColor.atTone(t(60)),
wind = baseColor.atTone(t(65)),
windDark = baseColor.atTone(t(45)),
lightningBolt = baseColor.atTone(t(90)),
hot = baseColor.atTone(t(55)),
cold = baseColor.atTone(t(55)),
)
if (tn > lower) {
return (tn + diff).toInt()
}
return tn.toInt()
}
}

View File

@@ -364,7 +364,8 @@ fun CurrentWeather(
end = 8.dp
),
icon = weatherIconById(forecast.icon),
night = forecast.night
night = forecast.night,
WeatherIconDefaults.colors(MaterialTheme.colorScheme.surface)
)
}
}
@@ -485,8 +486,10 @@ fun WeatherTimeSelector(
val listState = rememberLazyListState()
val colors = WeatherIconDefaults.colors()
val selectedColors = WeatherIconDefaults.monochromeColors(MaterialTheme.colorScheme.secondary)
val colors = WeatherIconDefaults.colors(MaterialTheme.colorScheme.surfaceBright)
val selectedColors = WeatherIconDefaults.themedColors(
MaterialTheme.colorScheme.secondary,
)
LazyRow(
state = listState,
@@ -587,8 +590,10 @@ fun WeatherDaySelector(
val dateFormat = SimpleDateFormat("EEE")
val context = LocalContext.current
val colors = WeatherIconDefaults.colors()
val selectedColors = WeatherIconDefaults.monochromeColors(MaterialTheme.colorScheme.secondary)
val colors = WeatherIconDefaults.colors(MaterialTheme.colorScheme.surfaceBright)
val selectedColors = WeatherIconDefaults.themedColors(
MaterialTheme.colorScheme.secondary,
)
val listState = rememberLazyListState()
LazyRow(