Skip to content

Instantly share code, notes, and snippets.

@davebren
Created January 17, 2022 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davebren/7bc82875323b4380411a7d28b54f0dbf to your computer and use it in GitHub Desktop.
Save davebren/7bc82875323b4380411a7d28b54f0dbf to your computer and use it in GitHub Desktop.
RGB / HSL conversions, dynamic pressed state color
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