【问题标题】:Align two texts by font's ascent instead of baseline in Jetpack Compose在 Jetpack Compose 中通过字体的上升而不是基线对齐两个文本
【发布时间】:2021-12-30 12:51:40
【问题描述】:

我知道如何将 Jetpack Compose 中的文本与基线对齐。

但是现在我需要通过ascent 这两种字体中较大的一种来对齐两个不同大小的文本,它们在Row 中彼此跟随。如果有意义的话,我想将其视为“按顶部基线”对齐两个文本。 Modifier.align(Alignment.Top) 不起作用,因为它不会按上升对齐,而是按布局的顶部对齐,然后文本在顶部没有正确对齐。

我试图看看如何做到这一点,但显然没有现成的函数或修饰符?我什至没有找到在 Compose 中访问 Text 的 ascent 属性等的方法。所以不确定这怎么可能?

感谢您的任何提示! :)

编辑:这是使用Alignment.Top 时的样子。但我希望这两个文本在顶部对齐。

【问题讨论】:

标签: android android-jetpack-compose android-jetpack-compose-text


【解决方案1】:

所有关于文本布局的信息都可以用onTextLayoutText 参数检索。在这种情况下,您需要一个可以使用getLineBottom 检索的行号和一个可以在layoutInput.style.fontSize 中找到的实际字体大小。

我同意如果你可以使用一些简单的方法来做这件事会更容易,所以我已经为你的 feature request 加了星标,但现在你可以通过以下方式计算它:

onTextLayout = { textLayoutResult ->
    val ascent = textLayoutResult.getLineBottom(0) - textLayoutResult.layoutInput.run {
        with(density) {
            style.fontSize.toPx()
        }
    }
},

对齐两个文本的完整示例:

val ascents = remember { mutableStateMapOf<Int, Float>() }
val texts = remember {
    listOf(
        "Big text" to 80.sp,
        "Small text" to 20.sp,
    )
}
Row(
    Modifier
        .drawBehind {
            ascents.maxOfOrNull { it.value }?.let {
                drawLine(Color.Red, Offset(0f, it), Offset(size.width, it))
            }
        }
) {
    texts.forEachIndexed { i, info ->
        Text(
            info.first,
            fontSize = info.second,
            onTextLayout = { textLayoutResult ->
                ascents[i] = textLayoutResult.getLineBottom(0) - textLayoutResult.layoutInput.run {
                    with(density) {
                        style.fontSize.toPx()
                    }
                }
            },
            modifier = Modifier
                .alpha(if (ascents.count() == texts.count()) 1f else 0f)
                .layout { measurable, constraints ->
                    val placeable = measurable.measure(constraints)
                    val maxAscent = ascents.maxOfOrNull { it.value } ?: 0f
                    val ascent = ascents[i] ?: 0f
                    val yOffset = if (maxAscent == ascent) 0 else (maxAscent - ascent).toInt()
                    layout(placeable.width, placeable.height - yOffset) {
                        placeable.place(0, yOffset)
                    }
                }
        )
    }
}

结果:

【讨论】:

  • 感谢菲利普的回答!我非常感谢您抽出宝贵的时间并从中制作一个工作样本!这确实似乎工作正常 - 我会采用您的解决方案 :) 这是一个有效的解决方案 - 这很好 - 但希望 Jetpack Compose 团队可以开箱即用地提供这个。而且我不知道如何攀登,所以也谢谢你!
【解决方案2】:

一种解决方法是您可以根据需要调整 y 轴偏移修改器。

Text(text = "Second", modifier = Modifier.offset(x = 0.dp, y = 5.dp))

如果您想根据需要增加第一个文本,也可以为偏移设置负值。

【讨论】:

  • 是的,这是一种选择。但对我来说感觉很hackish,价值取决于使用的字体。如果在 Compose 中没有适当的解决方案,这将是我将实施的最后手段和解决方法。老实说,如果它不存在,那将是一个惊喜。我可能会为此提交一个错误。
猜你喜欢
  • 2021-11-15
  • 1970-01-01
  • 2020-06-09
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多