Home > front end >  Jetpack Compose Canvas drawText color blending?
Jetpack Compose Canvas drawText color blending?

Time:12-09

Assume I have the following code in compose below.

A background magenta circle with a text on top with a default black color.

enter image description here

I would like to blend the text color to White when it is above the circle.

Canvas(
    modifier = Modifier.size(256.dp),
    onDraw = {
        drawCircle(
            color = Color.Magenta,
            radius = 50f,
            center = Offset(
                x = size.width / 2,
                y = size.height  / 2),
        )
        val textSize = textMeasurer.measure(text = AnnotatedString("A"))
        drawText(
            textMeasurer = textMeasurer,
            text = "A",
            style = TextStyle(
                color = Color.Black,
                fontSize = 14.sp
            ),
            topLeft = Offset(
                x = size.width / 2 - 100f - (textSize.size.width / 2),
                y = size.height  / 2 - (textSize.size.height / 2)
            )
        )
        drawText(
            textMeasurer = textMeasurer,
            text = "B",
            style = TextStyle(
                color = Color.Black,
                fontSize = 14.sp
            ),
            topLeft = Offset(
                x = size.width / 2 - (textSize.size.width / 2),
                y = size.height  / 2 - (textSize.size.height / 2)
            )
        )
    }
)

I have tried using BlendMode on the cirle in a lot of different configurations but I'm unable to make it work. And drawText doesn't have a blend mode that I can see.

Is there an easy way to achieve blending to make the text above the circle white?

CodePudding user response:

You either need to set alpha of Composable you want to use blendMode with less than 1f or use layer you want to draw source and destination in. Lowering alpha adds layer under the hood which both are basically same thing.

enter image description here

@Composable
private fun BlendModeSample() {

    val textMeasurer = rememberTextMeasurer()

    val infiniteTransition = rememberInfiniteTransition()


    val offset by infiniteTransition.animateFloat(
        initialValue = -1f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis = 3000),
            repeatMode = RepeatMode.Reverse
        )
    )
    Canvas(
        modifier = Modifier.size(256.dp),
        onDraw = {

            val textSize = textMeasurer.measure(text = AnnotatedString("A"))
            drawText(
                textMeasurer = textMeasurer,
                text = "A",
                style = TextStyle(
                    color = Color.Black,
                    fontSize = 14.sp
                ),
                topLeft = Offset(
                    x = size.width / 2 - 100f - (textSize.size.width / 2),
                    y = size.height / 2 - (textSize.size.height / 2)
                )
            )


            drawWithLayer {

                // Destination
                drawText(
                    textMeasurer = textMeasurer,
                    text = "B",
                    style = TextStyle(
                        color = Color.Black,
                        fontSize = 14.sp
                    ),
                    topLeft = Offset(
                        x = size.width / 2 - (textSize.size.width / 2),
                        y = size.height / 2 - (textSize.size.height / 2)   offset * 100f
                    ),

                    )

                // Source
                drawCircle(
                    color = Color.Magenta,
                    radius = 50f,
                    center = Offset(
                        x = size.width / 2,
                        y = size.height / 2
                    ),
                    blendMode = BlendMode.SrcOut
                )
            }


        }
    )
}

You can also check out using blend modes to build a rating bar.

Jetpack Compose: How to create a rating bar?

  • Related