在 API 29 以下编写 setShadowLayer 替代方案

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

所以实际上我有一个修饰符扩展函数来在可组合项中显示阴影。我正在使用在此 answer 中创建的代码。

这是代码:

fun Modifier.advancedShadow(
    color: Color = Color.Black,
    alpha: Float = 1f,
    cornersRadius: Dp = 0.dp,
    shadowBlurRadius: Dp = 0.dp,
    offsetY: Dp = 0.dp,
    offsetX: Dp = 0.dp
) = drawBehind {

    val shadowColor = color.copy(alpha = alpha).toArgb()
    val transparentColor = color.copy(alpha = 0f).toArgb()

    drawIntoCanvas {
        val paint = Paint()
        val frameworkPaint = paint.asFrameworkPaint()
        frameworkPaint.color = transparentColor
        frameworkPaint.setShadowLayer(
            shadowBlurRadius.toPx(),
            offsetX.toPx(),
            offsetY.toPx(),
            shadowColor
        )
        it.drawRoundRect(
            0f,
            0f,
            this.size.width,
            this.size.height,
            cornersRadius.toPx(),
            cornersRadius.toPx(),
            paint
        )
    }
}

问题是当我在 API 29 以下的设备中使用该功能时,阴影不显示,经过一些研究发现

setShadowLayer
仅支持高于 28 的 API 级别(android docs) 。那么我如何设法在下面的 API 29 中显示阴影呢?

android-jetpack-compose hardware-acceleration modifier
1个回答
0
投票

如果禁用硬件加速,它实际上可以在低于 29 的 API 上工作,但我们知道 Compose 默认使用硬件加速,并且不会公开任何直接修改行为的方法。但是,我将

ComposeView
包装在
AndroidView
中,强制它使用软件加速,作为使用
setShadowLayer
等 API 的黑客手段。这是我的一段代码中的随机示例:

AndroidView(
        modifier = modifier
            .fillMaxWidth()
            .height(108.dp),
        factory = { context ->
            ComposeView(context).apply {
                setLayerType(View.LAYER_TYPE_SOFTWARE, null)
            }
        },
        update = { composeView ->
            composeView.setContent {
                Row(
                    modifier = modifier
                        .fillMaxWidth()
                        .height(108.dp)
                        .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
                        .drawWithContent {
                            val blacknavy = Color(4, 16, 28)

                            drawRect(
                                color = blacknavy, alpha = 0.75f,
                                size = size,
                            )

                            drawContent()

                            if (isSelected) {
                                val bluey = Color(62, 137, 218, 255)
                                val neoSolid = Paint()
                                val neoGlow = Paint()

                                drawIntoCanvas { canvas ->
                                    neoSolid.color = bluey
                                    neoSolid.strokeWidth = 4f
                                    neoSolid.style = PaintingStyle.Stroke
                                    neoSolid.strokeJoin = StrokeJoin.Round
                                    neoSolid.strokeCap = StrokeCap.Round

                                    val neoRealGlow = neoGlow
                                        .asFrameworkPaint()
                                        .apply {
                                            set(neoSolid.asFrameworkPaint())
                                            color = Color.Transparent.toArgb()
                                            strokeWidth = 1f
                                            //maskFilter = BlurMaskFilter(15f, BlurMaskFilter.Blur.NORMAL)
                                            setShadowLayer(
                                                30f,
                                                0f,
                                                0f,
                                                Color.Red.copy(alpha = 0.9f)
                                                    .toArgb()
                                            )
                                        }


                                    canvas.drawLine(
                                        Offset(size.width, 0f),
                                        Offset(size.width, size.height),
                                        neoRealGlow.asComposePaint()
                                    )

                                    canvas.drawLine(
                                        Offset(size.width, 0f),
                                        Offset(size.width, size.height),
                                        neoSolid
                                    )
                                }
                            }
                        }
                        .clickable(
                            interactionSource = remember { MutableInteractionSource() },
                            indication = rememberRipple(),
                            onClick = onClick
                        ),
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Icon(
                        imageVector = icon,
                        contentDescription = "",
                        tint = Color.White
                    )
                }
            }
        },
    )
© www.soinside.com 2019 - 2024. All rights reserved.