Created
January 17, 2022 16:13
-
-
Save davebren/7bc82875323b4380411a7d28b54f0dbf to your computer and use it in GitHub Desktop.
RGB / HSL conversions, dynamic pressed state color
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
package eski.utils | |
import android.graphics.Color | |
import androidx.annotation.ColorInt | |
import androidx.core.graphics.blue | |
import androidx.core.graphics.green | |
import androidx.core.graphics.red | |
import com.ministrybrands.genesisapp.models.Config | |
import kotlin.math.abs | |
import kotlin.math.max | |
import kotlin.math.min | |
import kotlin.math.roundToInt | |
fun rgbToHsl(red: Int, green: Int, blue: Int): ColorHsl { | |
val redNormalized = red / 255f | |
val greenNormalized = green / 255f | |
val blueNormalized = blue / 255f | |
val channelMax = max(max(redNormalized, greenNormalized), blueNormalized) | |
val channelMin = min(min(redNormalized, greenNormalized), blueNormalized) | |
val channelDelta = channelMax - channelMin | |
var hue = when { | |
channelDelta == 0f -> 0f | |
channelMax == redNormalized -> (((greenNormalized - blueNormalized) / channelDelta) % 6) * 60f | |
channelMax == greenNormalized -> ((blueNormalized - redNormalized) / channelDelta + 2) * 60f | |
else -> ((redNormalized - greenNormalized) / channelDelta + 4) * 60f | |
} | |
if (hue < 0) hue += 360f | |
val lightnessNormalized = (channelMax + channelMin) / 2f | |
val lightness = (lightnessNormalized * 100f).roundToInt() | |
val saturationNormalized = if (channelDelta == 0f) 0f else channelDelta / (1f - abs(2f * lightnessNormalized - 1f)) | |
val saturation = (saturationNormalized * 100f).roundToInt() | |
return ColorHsl(hue.roundToInt(), saturation, lightness) | |
} | |
fun hslToRgb(hue: Int, saturation: Int, lightness: Int): ColorRgb { | |
val hueNormalized = hue / 360f | |
val saturationNormalized = saturation / 100f | |
val lightnessNormalized = lightness / 100f | |
if (saturationNormalized == 0f) { | |
val rgb = (lightnessNormalized * 255f).roundToInt() | |
return ColorRgb(rgb, rgb, rgb) | |
} | |
val q = if (lightnessNormalized < 0.5f) { | |
lightnessNormalized * (1f + saturationNormalized) | |
} else { | |
lightnessNormalized + saturationNormalized - (lightnessNormalized * saturationNormalized) | |
} | |
val p = 2f * lightnessNormalized - q | |
val red = hueToRgb(p, q, hueNormalized + 1f / 3f) | |
val green = hueToRgb(p, q, hueNormalized) | |
val blue = hueToRgb(p, q, hueNormalized - 1f / 3f) | |
return ColorRgb((red * 255f).roundToInt(), (green * 255f).roundToInt(), (blue * 255f).roundToInt()) | |
} | |
private fun hueToRgb(p: Float, q: Float, tParam: Float): Float { | |
var t = tParam | |
if (t < 0f) t += 1 | |
if (t > 1f) t -= 1 | |
if (t < 1f / 6f) return p + (q - p) * 6f * t | |
if (t < 1f / 2f) return q | |
if (t < 2f / 3f) return p + (q - p) * (2f / 3f - t) * 6f | |
return p | |
} | |
inline val @receiver:ColorInt Int.pressedColor: Int | |
get() { | |
val backgroundColor = Config.appearance.actionColor | |
val backgroundColorHsl = rgbToHsl(backgroundColor.red, backgroundColor.green, backgroundColor.blue) | |
val pressedLightness = if (backgroundColorHsl.lightness < 25) { | |
backgroundColorHsl.lightness + 15 // Make dark buttons lighter when pressed. | |
} else { | |
backgroundColorHsl.lightness - 15 // Make light buttons darker when pressed. | |
} | |
val pressedColorRgb = hslToRgb(backgroundColorHsl.hue, backgroundColorHsl.saturation, pressedLightness) | |
return Color.rgb(pressedColorRgb.red, pressedColorRgb.green, pressedColorRgb.blue) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment