Jetpack compose Canvas 混合模式无法按预期工作

问题描述 投票:0回答:2

我正在尝试将混合模式应用于 Jetpack compose 画布中的两个形状。基于这个博客,我大致知道预期的输出应该是什么样子,尽管我没有得到类似的结果。

例如,使用以下简单的 Box + Canvas,具有两种形状,使用混合模式

SrcIn

Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier.size(290.dp)
        ) {
            val sizeInPx = with(LocalDensity.current) { 150.dp.toPx() }

            Canvas(
                modifier = Modifier.fillMaxSize()
            ) {
                    drawCircle(
                        color = Color.Red,
                        radius = sizeInPx,
                    )

                    drawRect(
                        color = Color.Blue,
                        size = Size(sizeInPx, sizeInPx),
                        blendMode = BlendMode.SrcIn
                    )

            }
}

我期望有一个红色圆圈,以及一个剪裁成红色圆圈形状的蓝色正方形。然而输出的 UI 就像 no blend mode has been added at all

我做错了什么?

android android-jetpack-compose android-canvas android-jetpack-compose-canvas
2个回答
4
投票

将 alpha 更改为小于 1f 会创建一个图层作为缓冲区,这就是它起作用的原因。如果您不想更改 alpha,实现此目的的其他方法是直接使用图层。你可以在这里看到我的回答

Canvas(modifier = canvasModifier) {

    val canvasWidth = size.width.roundToInt()
    val canvasHeight = size.height.roundToInt()

    with(drawContext.canvas.nativeCanvas) {
        val checkPoint = saveLayer(null, null)

        drawCircle(
              color = Color.Red,
              radius = sizeInPx,
        )

        drawRect(
            color = Color.Blue,
            size = Size(sizeInPx, sizeInPx),
            blendMode = BlendMode.SrcIn
        )
        restoreToCount(checkPoint)
    }
}

在 Painter 代码中,Android 团队将其用作

private fun configureAlpha(alpha: Float) {
    if (this.alpha != alpha) {
        val consumed = applyAlpha(alpha)
        if (!consumed) {
            if (alpha == DefaultAlpha) {
                // Only update the paint parameter if we had it allocated before
                layerPaint?.alpha = alpha
                useLayer = false
            } else {
                obtainPaint().alpha = alpha
                useLayer = true
            }
        }
        this.alpha = alpha
    }
}

并检查Alpha以应用图层

  fun DrawScope.draw(
        size: Size,
        alpha: Float = DefaultAlpha,
        colorFilter: ColorFilter? = null
    ) {
        configureAlpha(alpha)
        configureColorFilter(colorFilter)
        configureLayoutDirection(layoutDirection)

        // b/156512437 to expose saveLayer on DrawScope
        inset(
            left = 0.0f,
            top = 0.0f,
            right = this.size.width - size.width,
            bottom = this.size.height - size.height
        ) {

            if (alpha > 0.0f && size.width > 0 && size.height > 0) {
                if (useLayer) {
                    val layerRect = Rect(Offset.Zero, Size(size.width, size.height))
                    // TODO (b/154550724) njawad replace with RenderNode/Layer API usage
                    drawIntoCanvas { canvas ->
                        canvas.withSaveLayer(layerRect, obtainPaint()) {
                            onDraw()
                        }
                    }
                } else {
                    onDraw()
                }
            }
        }
    }
}

0
投票

在所有其他绘制命令之前调用

drawRect(Color.White, blendMode = BlendMode.Clear)
使其在我这边工作。

看来,预先使用混合模式会创建底层,让其他混合模式完全得到尊重。

© www.soinside.com 2019 - 2024. All rights reserved.