android - Jetpack compose Canvas 混合模式未按预期工作

标签 android android-jetpack-compose android-canvas android-jetpack-compose-canvas

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

例如,使用以下具有两个形状的简单 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

我做错了什么?

最佳答案

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

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()
                }
            }
        }
    }
}

关于android - Jetpack compose Canvas 混合模式未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73313025/

相关文章:

android - 画一个边缘光滑的圆

java - Android 绘制路径未填满封闭区域

android - 使用 react-native 在真实设备上获取红屏

java - Android如何用耳机按钮接听电话等?

java - 你能防止一遍又一遍地编写带有微小差异的代码吗?

android - 在 phonegap/html5 应用程序中垂直定位元素

android - 喷气背包中 +(...)% 颜色的表面组成

android - 检测 Jetpack Compose 上的滑动方向

android - Jetpack Compose - 边框上带有弧形的 CardView

android - 在填充的 android Canvas 上绘制一个透明圆圈