Reputation: 4982
Designers often building custom colors by putting existing colros from "our" custom theme one of top of another with alpha applied. How can I calculate resulting Color without applying multiple backgrounds one of top of another? Something like
val background = MaterialTheme.colors.MyDanger.copy(alpha = 0.12f) + MaterialTheme.colors.CustomTint16
Plus is not defined for Colors as it's not Commutative, but is there a way to just put one Color on top on another in Code and apply only result?
Upvotes: 8
Views: 2815
Reputation: 4994
Finally, I made this implementation on top of ColorUtils.blendARGB
.
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.core.graphics.ColorUtils
fun Color.blend(topColor: Color, ratio: Float = 0.5f): Color {
if (ratio == 0f) return this
if (ratio == 1f) return topColor
val intColor = ColorUtils.blendARGB(toArgb(), topColor.toArgb(), ratio)
return Color(intColor)
}
And usage (add a little extra green to background):
modifier = Modifier
.background(MaterialTheme.colorScheme.background.blend(Green200))
Actually, .compositeOver()
do the same, but in weird way: it is extension for extraColor. You should write extraColor.compositeOver(mainColor)
. And not useful in case when you need to add extraColor conditionally.
Also, compositeOver
not support proportions (ratio
in my suggested extension).
But finally, code on extraColor.compositeOver(mainColor)
is the same as mainColor.blend(extraColor, 0.5f)
.
Upvotes: 0
Reputation: 4982
val result = color1.compositeOver(color2)
Is what I was looking for
Upvotes: 13
Reputation: 775
Example1:
// Ratio value has to be 0.5 to achive even mix.
//The 3rd argument is ratio(the proportion while blending the colors). eg.
//If you want 30% of color1 & 70% of color2, then do ColorUtils.blendARGB(***, ***, 0.3F);
int resultColor = androidx.core.graphics.ColorUtils.blendARGB(color1, color2, 0.5F);
Example2:
public static int mixColor(int color1, int color2, float ratio) {
final float inverse = 1 - ratio;
float a = (color1 >>> 24) * inverse + (color2 >>> 24) * ratio;
float r = ((color1 >> 16) & 0xFF) * inverse + ((color2 >> 16) & 0xFF) * ratio;
float g = ((color1 >> 8) & 0xFF) * inverse + ((color2 >> 8) & 0xFF) * ratio;
float b = (color1 & 0xFF) * inverse + (color2 & 0xFF) * ratio;
return ((int) a << 24) | ((int) r << 16) | ((int) g << 8) | (int) b;
}
Upvotes: 1