所以实际上我有一个修饰符扩展函数来在可组合项中显示阴影。我正在使用在此 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 中显示阴影呢?
如果禁用硬件加速,它实际上可以在低于 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
)
}
}
},
)