如何在 Jetpack Compose 的其他画布项目中对齐中心文本

发布于 2023-02-14 17:43:49

我想在我的画布中对齐我的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
                    )
                }
            }
        }
    }
}

实际产量

预期产出

当文本为“极高”时

当文本为“非常高”时

查看更多

1楼回答 2023-02-08

您对 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
            )
        )
    }

请登录后再发布答案,点击登录