And*_*ill 3 android android-canvas android-jetpack-compose android-jetpack-compose-canvas
假设我在下面编写了以下代码。
背景洋红色圆圈,顶部有默认黑色的文本。
当文本颜色位于圆圈上方时,我想将其混合为白色。
Canvas(
modifier = Modifier.size(256.dp),
onDraw = {
drawCircle(
color = Color.Magenta,
radius = 50f,
center = Offset(
x = size.width / 2,
y = size.height / 2),
)
val textSize = textMeasurer.measure(text = AnnotatedString("A"))
drawText(
textMeasurer = textMeasurer,
text = "A",
style = TextStyle(
color = Color.Black,
fontSize = 14.sp
),
topLeft = Offset(
x = size.width / 2 - 100f - (textSize.size.width / 2),
y = size.height / 2 - (textSize.size.height / 2)
)
)
drawText(
textMeasurer = textMeasurer,
text = "B",
style = TextStyle(
color = Color.Black,
fontSize = 14.sp
),
topLeft = Offset(
x = size.width / 2 - (textSize.size.width / 2),
y = size.height / 2 - (textSize.size.height / 2)
)
)
}
)
Run Code Online (Sandbox Code Playgroud)
我尝试过在许多不同的配置中在圆圈上使用 BlendMode,但我无法使其工作。而且drawText 没有我可以看到的混合模式。
有没有一种简单的方法来实现混合,使圆圈上方的文字变成白色?
您要么需要设置 Composable 的 alpha,想要使用小于 1f 的 blendMode,要么使用想要在其中绘制源和目标的图层。降低 alpha 会在引擎盖下添加图层,这两者基本上是相同的事情。
Jetpack Compose 将 PorterDuffMode 应用于图像
fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) {
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
block()
restoreToCount(checkPoint)
}
}
Run Code Online (Sandbox Code Playgroud)
由于drawText没有 BlendMode 参数,我们需要将其绘制为目标,还添加了动画来通过 BlendMode 演示颜色变化。
@Composable
private fun BlendModeSample() {
val textMeasurer = rememberTextMeasurer()
val infiniteTransition = rememberInfiniteTransition()
val offset by infiniteTransition.animateFloat(
initialValue = -1f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 3000),
repeatMode = RepeatMode.Reverse
)
)
Canvas(
modifier = Modifier.size(256.dp),
onDraw = {
val textSize = textMeasurer.measure(text = AnnotatedString("A"))
drawText(
textMeasurer = textMeasurer,
text = "A",
style = TextStyle(
color = Color.Black,
fontSize = 14.sp
),
topLeft = Offset(
x = size.width / 2 - 100f - (textSize.size.width / 2),
y = size.height / 2 - (textSize.size.height / 2)
)
)
drawWithLayer {
// Destination
drawText(
textMeasurer = textMeasurer,
text = "B",
style = TextStyle(
color = Color.Black,
fontSize = 14.sp
),
topLeft = Offset(
x = size.width / 2 - (textSize.size.width / 2),
y = size.height / 2 - (textSize.size.height / 2) + offset * 100f
),
)
// Source
drawCircle(
color = Color.Magenta,
radius = 50f,
center = Offset(
x = size.width / 2,
y = size.height / 2
),
blendMode = BlendMode.SrcOut
)
}
}
)
}
Run Code Online (Sandbox Code Playgroud)
您还可以查看使用混合模式来构建评级栏。