我正在 Jetpack Compose 中创建一个自定义组件,需要在组件边界之外进行绘制,这可能会在 BlendMode 中使用透明颜色。我正在使用 CompositingStrategy 来处理这个问题,但面临一些问题。
下面是该问题的重现示例。
@Composable
@Preview(widthDp = 600, heightDp = 600)
private fun Preview() {
Column(
Modifier.fillMaxSize().background(Color.Blue),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Canvas(
modifier = Modifier.size(250.dp).graphicsLayer(
compositingStrategy = CompositingStrategy.Offscreen,
// compositingStrategy = CompositingStrategy.ModulateAlpha
).border(1.dp, color = Color.Black)
) {
drawCircle(
Color.Red,
(size.minDimension/2f)*1.5f
)
drawCircle(
Color.Transparent,
(size.minDimension/2f)*1f,
blendMode = BlendMode.Src
)
}
}
}
使用
:正确处理 Alpha,但将绘图裁剪为组件的大小。CompositingStrategy.Offscreen
使用
:解决了剪切问题,但透明颜色内圆不起作用。CompositingStrategy.ModulateAlpha
那么有没有办法同时实现这两个目标呢?
下面是我期望的结果,其中内圈是透明的,所以蓝色背景是可见的:
您可以使用“差异”路径操作创建您提到的形状: 为外圆创建一条路径,为内圆创建一条路径,然后取两条路径之间的差值,这给出了您提到的形状。
代码:
@Composable
@Preview(widthDp = 600, heightDp = 600)
fun App() {
Column(
Modifier
.fillMaxSize()
.background(Color.Blue),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Canvas(
modifier = Modifier
.size(250.dp)
.border(1.dp, color = Color.Black)
) {
val cx = size.width/2f
val cy = size.height/2f
val c = Offset(cx, cy)
val r = (size.minDimension/2f)
val outerPath = Path().apply {
addOval(
oval = Rect(
center = c,
radius = r*1.5f
)
)
}
val innerPath = Path().apply {
addOval(
oval = Rect(
center = c,
radius = r
)
)
}
val path = Path().apply {
op(outerPath, innerPath, PathOperation.Difference)
}
drawPath(
path = path,
color = Color.Red
)
}
}
}
结果: