我想在我的画布中对齐我的drawText
视图中心。我在 answer 的帮助下绘制了我的图像视图。现在我想在上面 drawText
,但我的文本在我的视图中心。这有点复杂,但我会用图像向您展示。
@OptIn(ExperimentalTextApi::class)
@Composable
fun DrawProgressBar() {
val rangeComposition = RangeComposition()
val itemLst = rangeComposition.bpExplained
val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue))
val progressBarPointer = rangeComposition.findReadingWithPointer(142, 90).second
val textMeasurer = rememberTextMeasurer()
textMeasurer.measure(text = AnnotatedString("Extremely high"))
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.background(Color.White)
) {
//triangle size
val rectSize = Size(12.dp.toPx(), 9.dp.toPx())
val strokeWidth = 8.dp
val canvasWidth = size.width
val canvasHeight = size.height
val strokeWidthPx = density.run { strokeWidth.toPx() }
val dashedPathEffect =
PathEffect.dashPathEffect(floatArrayOf(canvasHeight / 38, canvasHeight / 38), 0f)
val rect = Rect(Offset.Zero, rectSize)
val trianglePath = Path().apply {
moveTo(rect.bottomCenter.x, rect.bottomCenter.y)
lineTo(rect.topRight.x, rect.topRight.y)
lineTo(rect.topLeft.x, rect.topLeft.y)
close()
}
val progressBarPointerInPixel = (progressBarPointer / 100f) * canvasWidth
drawIntoCanvas { canvas ->
// I want to fix this in centre of drawOutline
drawText(
textMeasurer = textMeasurer,
text = "Extremely high",
topLeft = Offset((progressBarPointerInPixel), 2.dp.toPx()),
style = TextStyle(fontSize = 12.sp)
)
translate(progressBarPointerInPixel, 20.dp.toPx()) {
canvas.drawOutline(
outline = Outline.Generic(trianglePath),
paint = Paint().apply {
color = Color.DarkGray
pathEffect = PathEffect.cornerPathEffect(rect.maxDimension / 3)
}
)
}
drawLine(
start = Offset(x = 0f, y = (canvasHeight / 4) * 3),
end = Offset(x = canvasWidth, y = (canvasHeight / 4) * 3),
color = Color.Gray,
strokeWidth = strokeWidthPx,
cap = StrokeCap.Round,
)
drawLine(
color = Color.White,
start = Offset(x = progressBarPointerInPixel, y = (canvasHeight / 4) * 3),
end = Offset(x = progressBarPointerInPixel + strokeWidthPx / 2, y = (canvasHeight / 4) * 3),
strokeWidth = strokeWidthPx,
)
drawLine(
brush = brush,
start = Offset(x = 0f, y = (canvasHeight / 4) * 3),
end = Offset(x = progressBarPointerInPixel, y = (canvasHeight / 4) * 3),
strokeWidth = strokeWidthPx,
cap = StrokeCap.Round,
)
drawArc(
topLeft = Offset(
x = progressBarPointerInPixel,
y = ((canvasHeight / 4) * 3) - strokeWidthPx / 2
),
size = Size(strokeWidthPx, strokeWidthPx),
color = Color.White,
startAngle = -90f,
sweepAngle = 180f,
useCenter = true
)
itemLst.forEachIndexed { index, rangeItem ->
val endPointInPixel = (rangeItem.endPoint / 100f) * canvasWidth
if (index != itemLst.lastIndex) {
drawLine(
start = Offset(x = endPointInPixel, y = 30.dp.toPx()),
end = Offset(x = endPointInPixel, y = canvasHeight),
color = Color.Black,
strokeWidth = 1.2.dp.toPx(),
pathEffect = dashedPathEffect
)
}
}
}
}
}
实际产量
预期产出
当文本为“极高”时
当文本为“非常高”时
您对 Text
和三角形使用相同的水平偏移。Text
的右侧水平偏移量是三角形的中心 - textWidth/2。
您可以使用:
Canvas(modifier = Modifier.fillMaxSize()){
val rectSize = Size (60f,60f)
//... your code
val triangleLeftOffset = 150f
drawIntoCanvas { canvas ->
translate (triangleLeftOffset,70f){
canvas.drawOutline(
outline = Outline.Generic(trianglePath),
//...
)
}
}
val textLayoutResult: TextLayoutResult =
textMeasurer.measure(
text = AnnotatedString("Extremely high"),
style = TextStyle(color = Color.Blue, fontSize = 20.sp)
)
val textSize = textLayoutResult.size
val triangleCenterX = triangleLeftOffset + rectSize.width/2
drawText(
textLayoutResult = textLayoutResult,
topLeft = Offset(
x = triangleCenterX - textSize.width/2f,
y = 0f
)
)
}