DmitryBorodin
DmitryBorodin

Reputation: 4982

Jetpack Compose how to build custom Color by overlaying 2 existing colors in code?

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

Answers (3)

Pavel Shorokhov
Pavel Shorokhov

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

DmitryBorodin
DmitryBorodin

Reputation: 4982

val result = color1.compositeOver(color2)

Is what I was looking for

Upvotes: 13

Halifax
Halifax

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

Related Questions