我试图使用drawBehind和drawIntoCanvas在jetpack compose中实现自定义阴影修改器,这在api 28(pie)中工作得很好,但模糊效果在api 26(oreo)中没有按预期工作,它只在画布中绘制一个矩形但 MaskFilter 不起作用。
有什么原因吗?不支持 BlurMaskFilter 吗?
我附上了修改器函数的代码片段和相关图片。
fun Modifier.shadowCustom(
color: Color = Color.Black,
offsetX: Dp = 0.dp,
offsetY: Dp = 0.dp,
blurRadius: Dp = 0.dp,
shapeRadius: Dp = 0.dp,
) = composed {
val paint: Paint = remember { Paint() }
val blurRadiusPx = blurRadius.px(LocalDensity.current)
val maskFilter = remember {
BlurMaskFilter(blurRadiusPx, BlurMaskFilter.Blur.NORMAL)
}
drawBehind {
drawIntoCanvas { canvas ->
val frameworkPaint = paint.asFrameworkPaint()
if (blurRadius != 0.dp) {
frameworkPaint.maskFilter = maskFilter
}
frameworkPaint.color = color.toArgb()
val leftPixel = offsetX.toPx()
val topPixel = offsetY.toPx()
val rightPixel = size.width + leftPixel
val bottomPixel = size.height + topPixel
if (shapeRadius > 0.dp) {
val radiusPx = shapeRadius.toPx()
canvas.drawRoundRect(
left = leftPixel,
top = topPixel,
right = rightPixel,
bottom = bottomPixel,
radiusX = radiusPx,
radiusY = radiusPx,
paint = paint,
)
} else {
canvas.drawRect(
left = leftPixel,
top = topPixel,
right = rightPixel,
bottom = bottomPixel,
paint = paint,
)
}
}
}
}
private fun Dp.px(density: Density): Float =
with(density) { toPx() }
这是因为
BlurMaskFilter
仅适用于 Android API 28 (https://developer.android.com/topic/performance/hardware-accel#drawing-support) 的硬件加速。
您可以将应用程序或活动设置为停止硬件加速(不确定是否建议这样做,因为这可能会影响性能):
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
或者您可以尝试使用渐变方法来模拟阴影效果,如下所示(以下代码适合您的情况):
val bottomGradient = LinearGradientShader(
from = Offset(x = 0f, y = size.height),
to = Offset(x = 0f, y = size.height + blurRadius),
colors = listOf(color, Color.Transparent),
)
canvas.drawRoundRect(
left = leftPixel,
top = size.height + topPixel,
right = rightPixel,
bottom = bottomPixel + blurRadius,
radiusX = radiusPx,
radiusY = radiusPx,
paint = Paint().apply {
shader = bottomGradient
},
)
当然,您可以编辑
colorStops
和代码以匹配您想要的内容。它不能完全取代模糊效果,但它可以作为替代品,特别是如果您仅将其用于旧设备,而您将模糊用于新设备。
希望对您有所帮助。