使用 Jetpack Compose 精确地绘制文本

3
我尝试在Jetpack Compose中在圆形和正方形内绘制文本时遇到了这个问题。文本容器/容器(我不确定我们称之为什么),即浅红色矩形,它容纳实际文本的位置未居中。
我按照this答案进行操作,确保将文本精确地绘制在圆形的中心,但似乎仍不在圆形的中心位置。如我们所见,文本位于那个浅红色矩形的较低部分。
正如我们在这张图片中看到的那样,文本已经接触到圆形下部,而我们在上面有足够的空间。

这与基线有关吗?如何解决?

还是这是一个错误?

代码:

Box(
    modifier = Modifier
        .fillMaxSize()
        .background(Color.Green.copy(alpha = 0.2f))
        .padding(36.dp),
    contentAlignment = Alignment.Center
) {
    val textMeasurer = rememberTextMeasurer()
    val textToDraw = "O"
    val style = TextStyle(
        fontSize = 328.sp,
        background = Color.Red.copy(alpha = 0.2f)
    )
    val textLayoutResult = remember(textToDraw, style) {
        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
        )
    }
}

如果我将字体缩小(在上面的代码中约为176sp),它看起来像下面这样。这表明浅红色矩形在圆内完美居中,而不仅仅是它所包含的文本。

非常感谢您的帮助和建议。

1个回答

2

这可能与字体度量、平台在文本首行和末行底部添加的不均匀填充(也称为 includeFontPadding)有关。

为什么不尝试:

        val style = TextStyle(
            fontSize = 328.sp,
            background = Red.copy(alpha = 0.2f),
            platformStyle = PlatformTextStyle(includeFontPadding = false)
        )

这应该会给你一个更准确的结果:

enter image description here

由于像素精确度和字形本身中不可避免的填充,结果可能不会完全准确(用于绘制字符的实际图像)。


1
谢谢Alejandra的答案。但PlatformTextStyle已过时。 'constructor PlatformTextStyle(Boolean = ...)'已过时。 includeFontPadding添加到Android中以解决高脚本截断问题。然而,该问题自Android 28以来已被修复。Compose为Android 28之前的版本提供了修复程序。因此,需要includeFontPadding的初始原因在Compose上无效。增加此配置是为了迁移应用程序,在某些代码或设计依赖includeFontPadding=true行为的情况下使用,并将被删除。 - skafle
2
是的,抱歉这可能有点令人困惑。发生的事情是:创建了带有includeFontPadding的PlatformTextStyle构造函数作为已弃用的API,以指示这是一个兼容性API,而不是因为您不应该使用它。 最近,我们通过此更改http://r.android.com/2534105取消了弃用,将在下一个Compose UI版本中提供,以鼓励其使用,例如在这种情况下。谢谢! - Alejandra
1
非常感谢Ale的帮助。是的,includeFontPadding可以解决问题,正如你所提到的,特定字体相关的因素也会影响偏移。我尝试了在TextStyle中使用baselineShift,这有助于微调偏移。致敬。更多学习资源:这个这个 - skafle
1
@skafle 这正如我所料,需要进行一些基线计算,应该使用 baselineShift 来完成,知道这点很好。 - Thracian
1
@Alejandra,感谢您撰写如此出色的有关文本的文章。 - Thracian
我知道这个问题是针对Android的,但通常Compose技术也适用于Compose Multiplatform。我查了一下,这个答案似乎对Compose Multiplatform不起作用,因为有这个问题:https://github.com/JetBrains/compose-multiplatform/issues/2477 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接