jetpack compose blendMode 或 PorterDuff.Mode DST_IN

jetpack compose blendMode or PorterDuff.Mode DST_IN

我有一个模糊的背景位图和一个可水平滚动的行。我想实现的是背景图片必须只在行项目区域可见...

我尝试将 DST_IN 与混合模式一起应用,但没有成功。有什么想法可以在 Jetpack Compose 中实现吗?

我想要实现的是这个

我想要一个模糊版本的背景图像,它只在行项目中可见,这样滚动时它看起来就像行项目上的光泽镜面背景

您要么需要将 alpha 设置为小于 1f

    Canvas(
        modifier = Modifier
            .fillMaxSize()
            // Provide a slight opacity to for compositing into an
            // offscreen buffer to ensure blend modes are applied to empty pixel information
            // By default any alpha != 1.0f will use a compositing layer by default
            .graphicsLayer(alpha = 0.99f)
    ) {


        val dimension = (size.height.coerceAtMost(size.width) / 2f).toInt()

        drawImage(
            image = imageBitmapDst,
            dstSize = IntSize(dimension, dimension)
        )
        drawImage(
            image = imageBitmapSrc,
            dstSize = IntSize(dimension, dimension),
            blendMode = BlendMode.DstIn
        )
    }
}

或者在canvas

里面使用一层
 with(drawContext.canvas.nativeCanvas) {

    val checkPoint = saveLayer(null, null)

// Destination
    drawImage(
        image = dstImage,
        srcSize = IntSize(canvasWidth / 2, canvasHeight / 2),
        dstSize = IntSize(canvasWidth, canvasHeight),
    )

    // Source
    drawImage(
        image = srcImage,
        srcSize = IntSize(canvasWidth / 2, canvasHeight / 2),
        dstSize = IntSize(canvasWidth, canvasHeight),
        blendMode = BlendMode.DstIn

    )
    restoreToCount(checkPoint)
}

您可以查看此 tutorial 以了解有关混合模式的更多信息。

将 alpha 设置为小于 1f 可能看起来像是一种 hack,但 Image 的 Painter 源代码也使用它来决定是否创建图层

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

并为 Image

创建图层
    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()
                }
            }
        }
    }
}

我找到了方法https://medium.com/p/b0c5824b55d0