Thread
#compose
    c

    Can

    1 year ago
    Hey people! I feel like I'm missing something here. I'd like to apply a Porterduffmode / BlendMode to a Text so that it changes the color so that the lower half is white for example. Previously this could be achieved with "drawText" and a Porterduffmode but DrawScope doesn't support drawText and I feel like i can't apply a ColorFilter to Text. There might be some way by writing a custom Painter and add a colorfilter to it but this doesn't feel like a straightforward way to do this. Any ideas?
    d

    Denis

    1 year ago
    Hi, Can. Have you seen https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/BlendMode? I haven't tried it and don't understand it yet, but looks like it's what you need. To draw text into Canvas, you should use TextDelegate. Search this channel for usage examples If you get it work, please share the code! Interesting question.
    c

    Can

    1 year ago
    Hey Denis, thanks for the tip with TextDelegate - I think that's something I missed. I indeed found BlendMode but didn't manage to draw Text into a Canvas. I will definitely try it out!
    @Denis are you sure "TextDelegate" is supposed to be used by API consumers? I get a scary looking warning
    d

    Denis

    1 year ago
    @jim and @Siyamed talk about
    TextDelegate
    in this thread. I don't know if it won't change significantly in future releases. But basing on this message from @Adam Powell, there's no hidden magic (private APIs), and I think even if it'll change, it will stay accessible in some way. In the worst case you just copy the code to your project and keep using it. (Sorry for mentions, folks, but maybe you have something to add or correct me.)
    Adam Powell

    Adam Powell

    1 year ago
    "accessible in some way" in this case means you might need to copy/paste some of its implementation for stability across updates, its API is not stable/final for consumption as it is marked with
    @InternalFoundationTextApi
    c

    Can

    1 year ago
    @Adam Powell thanks for that!@Denis retried the code based on your suggestion and i feel like I'm doing something wrong. "DstAtop" is doing nothing at all, while I fee like it should do the trick:
    val displayedValue = displayedValue
            val textDelegate = if (displayedValue != null) {
                TextDelegate(
                    text = AnnotatedString("${displayedValue / 1_000L}"),
                    style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Bold),
                    density = Density(dm.density),
                    resourceLoader = LocalFontLoader.current
                ).layout(Constraints(), LayoutDirection.Ltr)
            } else {
                null
            }
    Canvas(
        Modifier.fillMaxSize()
    ) {
        if (textDelegate != null) {
            drawIntoCanvas {
                TextDelegate.paint(canvas = it, textDelegate)
            }
        }
    
        drawRect(
            color = Color.Red,
            topLeft = Offset(0f, 0f),
            size = Size(size.width, size.height),
            blendMode = BlendMode.DstAtop
        )
    }
    the bottom rect is not visible at all when setting "DstAtop". Can this be an emulator issue?
    Got the effect i was looking for thanks to @romainguy. Seems like adding an alpha to my Canvas did the trick. This seems like its a quite hidden API and tricky to find tbh. Final code would be:
    Canvas(
        Modifier
            .fillMaxSize()
            .alpha(0.99f)
    ) {
        if (textDelegate != null) {
            drawIntoCanvas {
                TextDelegate.paint(canvas = it, textDelegate)
            }
        }
    
        drawRect(
            color = Color.White,
            topLeft = Offset(0f, size.height - boxHeight),
            size = Size(size.width, boxHeight),
            blendMode = BlendMode.SrcAtop
        )
    }
    FYI @Denis
    Note ".alpha(0.99f)"
    r

    romainguy

    1 year ago
    You shouldn't need this alpha trick
    Using a layer is the proper way. @Nader Jawad can tell you more
    Setting an alpha value has the side effect of creating a layer
    Nader Jawad

    Nader Jawad

    1 year ago
    Yes, we need to have a transparent layer such that the text content can be used as a mask with the blendmode applied to it. As @romainguy mentioned, using alpha has a side effect of creating this layer. In the future there will be an explicit flag to force layer usage directly so using alpha as a side effect wouldn't be necessary.
    c

    Can

    1 year ago
    Thanks a lot @Nader Jawad and @romainguy for your help