Jetpack Compose Canvas中drawText与圆形的颜色混合实现
解决Jetpack Compose圆形上方文本变白的简便方法
方法一:固定位置文本直接指定颜色
如果文本位置固定(比如示例中的B完全落在圆形区域内),最直接的方式就是给圆形上的文本单独设置白色,其他区域文本保持黑色:
Canvas( modifier = Modifier.size(256.dp), onDraw = { val center = Offset(size.width / 2, size.height / 2) val textSize = textMeasurer.measure(text = AnnotatedString("A")) drawCircle( color = Color.Magenta, radius = 50f, center = center ) // 圆形外的文本用黑色 drawText( textMeasurer = textMeasurer, text = "A", style = TextStyle( color = Color.Black, fontSize = 14.sp ), topLeft = Offset( x = center.x - 100f - (textSize.size.width / 2), y = center.y - (textSize.size.height / 2) ) ) // 圆形上的文本直接用白色 drawText( textMeasurer = textMeasurer, text = "B", style = TextStyle( color = Color.White, fontSize = 14.sp ), topLeft = Offset( x = center.x - (textSize.size.width / 2), y = center.y - (textSize.size.height / 2) ) ) } )
方法二:动态判断文本位置(通用方案)
如果文本位置是动态的,不确定是否落在圆形内,可以通过计算文本中心到圆形中心的距离,动态切换文本颜色:
Canvas( modifier = Modifier.size(256.dp), onDraw = { val center = Offset(size.width / 2, size.height / 2) val radius = 50f val textSize = textMeasurer.measure(text = AnnotatedString("A")) drawCircle( color = Color.Magenta, radius = radius, center = center ) // 处理文本A:判断是否在圆形内 val aTopLeft = Offset( x = center.x - 100f - (textSize.size.width / 2), y = center.y - (textSize.size.height / 2) ) val aCenter = Offset( x = aTopLeft.x + textSize.size.width / 2, y = aTopLeft.y + textSize.size.height / 2 ) val aDistance = sqrt((aCenter.x - center.x).pow(2) + (aCenter.y - center.y).pow(2)) drawText( textMeasurer = textMeasurer, text = "A", style = TextStyle( color = if (aDistance <= radius) Color.White else Color.Black, fontSize = 14.sp ), topLeft = aTopLeft ) // 处理文本B:判断是否在圆形内 val bTopLeft = Offset( x = center.x - (textSize.size.width / 2), y = center.y - (textSize.size.height / 2) ) val bCenter = Offset( x = bTopLeft.x + textSize.size.width / 2, y = bTopLeft.y + textSize.size.height / 2 ) val bDistance = sqrt((bCenter.x - center.x).pow(2) + (bCenter.y - center.y).pow(2)) drawText( textMeasurer = textMeasurer, text = "B", style = TextStyle( color = if (bDistance <= radius) Color.White else Color.Black, fontSize = 14.sp ), topLeft = bTopLeft ) } )
方法三:裁剪图层覆盖(复杂场景适配)
如果需要批量处理多个文本,或文本形状不规则,可以用withClipPath裁剪出圆形区域,在区域内绘制白色文本覆盖黑色:
Canvas( modifier = Modifier.size(256.dp), onDraw = { val center = Offset(size.width / 2, size.height / 2) val radius = 50f val textSize = textMeasurer.measure(text = AnnotatedString("A")) // 绘制圆形背景 drawCircle( color = Color.Magenta, radius = radius, center = center ) // 绘制所有黑色文本 drawText( textMeasurer = textMeasurer, text = "A", style = TextStyle(color = Color.Black, fontSize = 14.sp), topLeft = Offset( x = center.x - 100f - (textSize.size.width / 2), y = center.y - (textSize.size.height / 2) ) ) val bTopLeft = Offset( x = center.x - (textSize.size.width / 2), y = center.y - (textSize.size.height / 2) ) drawText( textMeasurer = textMeasurer, text = "B", style = TextStyle(color = Color.Black, fontSize = 14.sp), topLeft = bTopLeft ) // 裁剪圆形区域,绘制白色文本覆盖原有黑色 withClipPath(Path().apply { addOval(Rect(center.x - radius, center.y - radius, center.x + radius, center.y + radius)) }) { drawText( textMeasurer = textMeasurer, text = "B", style = TextStyle(color = Color.White, fontSize = 14.sp), topLeft = bTopLeft ) } } )
内容的提问来源于stack exchange,提问作者AndreasLill
相关产品推荐
相关产品推荐

