如何在 Jetpack compose 中在另一个对象的中心绘制文本?

ska*_*fle 8 android drawtext android-canvas android-jetpack-compose android-jetpack-compose-canvas

我正在尝试在 Jetpack Compose 中的圆圈内绘制文本。

我画了一个圆,中心是画布的中心。

现在我想精确地在圆的中心绘制文本。

drawTextJetpack compose中的函数具有canvas参数topLeft,该参数需要Offset包含文本的矩形的左上角。我知道我不能通过圆心作为偏移量topLeft,如果我这样做,结果将如下所示,这不是我想要的。

尝试在圆心绘制文本

我希望文本恰好绘制在圆的中心。

这是代码:

Box(
    modifier = Modifier
        .fillMaxSize()
        .background(Color.Green.copy(alpha = 0.2f))
        .padding(36.dp),
    contentAlignment = Alignment.Center
) {
    val textMeasurer = rememberTextMeasurer()
    val textToDraw = "A"
    Canvas(modifier = Modifier.fillMaxSize()) {
        drawCircle(
            center = Offset(
                x = center.x,
                y = center.y
            ),
            radius = 350f,
            color = Color.Blue,
            style = Stroke(
                width = 8f
            )
        )

        drawText(
            textMeasurer = textMeasurer,
            text = textToDraw,
            style = TextStyle(
                fontSize = 150.sp,
                color = Color.Black,
                background = Color.Red.copy(alpha = 0.2f)
            ),
            topLeft = Offset(
                x = center.x,
                y = center.y
            )
        )
        drawPoints(
            points = listOf(Offset(center.x, center.y)),
            pointMode = PointMode.Points,
            cap = StrokeCap.Round,
            color = Color.Red,
            strokeWidth = 25f
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以像这样手动调整偏移以使其工作,但这不是最佳和自动的。

topLeft = Offset(
    x = center.x - 125,
    y = center.y - 270
),
Run Code Online (Sandbox Code Playgroud)

文字以圆圈为中心

如何才能做到这一点?感谢任何帮助。

注意:我为文本应用的浅红色背景只是为了可视化用于文本的底层矩形。我还在圆的中心画了一个点以使其更加清晰。

Thr*_*ian 10

您可以获得 TextLayoutResult,它返回包含文本的矩形的大小。Andy 通过将宽度的一半向左偏移并将高度的一半向顶部偏移,您可以将画布内的文本居中。

在此输入图像描述

val textMeasurer = rememberTextMeasurer()

val textToDraw = "A"

val style = TextStyle(
    fontSize = 150.sp,
    color = Color.Black,
    background = Color.Red.copy(alpha = 0.2f)
)
// Keys are to demonstrate that you can re-calculate block inside
// when any of them change. Otherwise remember results on each recomposition
val textLayoutResult = remember(textToDraw, style) {
    textMeasurer.measure(textToDraw, style)
}
Run Code Online (Sandbox Code Playgroud)

完整样本

@Preview
@Composable
private fun DrawTextAtCenterSample() {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Green.copy(alpha = 0.2f))
            .padding(36.dp),
        contentAlignment = Alignment.Center
    ) {
        val textMeasurer = rememberTextMeasurer()

        val textToDraw = "A"

        val style = TextStyle(
            fontSize = 150.sp,
            color = Color.Black,
            background = Color.Red.copy(alpha = 0.2f)
        )

        val textLayoutResult = remember(textToDraw) {
            textMeasurer.measure(textToDraw, style)
        }

        Canvas(modifier = Modifier.fillMaxSize()) {
            drawCircle(
                center = Offset(
                    x = center.x,
                    y = center.y
                ),
                radius = 350f,
                color = Color.Blue,
                style = Stroke(
                    width = 8f
                )
            )


            drawText(
                textMeasurer = textMeasurer,
                text = textToDraw,
                style = style,
                topLeft = Offset(
                    x = center.x - textLayoutResult.size.width / 2,
                    y = center.y - textLayoutResult.size.height / 2,
                )
            )
            drawPoints(
                points = listOf(Offset(center.x, center.y)),
                pointMode = PointMode.Points,
                cap = StrokeCap.Round,
                color = Color.Red,
                strokeWidth = 25f
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)