[英]Jetpack Compose, centering text without font padding?
I'm struggling with vertically centering text in Jetpack Compose version alpha-11.我在 Jetpack Compose alpha-11 版中遇到垂直居中文本问题。 It appears that my font has a significant amount of padding and I'm unable to find a way to disable it.
看来我的字体有大量填充,我无法找到禁用它的方法。 This has come up only once before on SO, as far as I can tell, here , but their answer of using a constraint layout seems to suggest that they simply positioned it absolutely, which isn't exactly a solution as much as a workaround, and something I'd like to avoid.
据我所知, 这在 SO 之前只出现过一次,但是他们对使用约束布局的回答似乎表明他们只是将其绝对定位,这与其说是一种解决方案,不如说是一种解决方案,和我想避免的事情。
You can see it clearly in the screenshot below.您可以在下面的屏幕截图中清楚地看到它。
The code for that looks like this:代码如下所示:
Column(verticalArrangement = Arrangement.Center) {
Text(
text = "Let's Go",
color = Color.White,
fontSize = 120.sp,
fontFamily = oswaldLightFontFamily(),
textAlign = TextAlign.Center,
modifier = Modifier.background(Color.Blue)
)
}
The arguments you would expect to position it -- verticalArrangement
and textAlign
-- do not do anything here but I'm including them to demonstrate what I've tried.您期望的 arguments 到 position 它 --
verticalArrangement
和textAlign
-- 在这里不执行任何操作,但我将它们包括在内以演示我的尝试。
My workaround so far has been to use Modifier.graphicsLayer(translationY = -25f)
to shift it up but that seems like a terrible hack for something that should be so straightforward.到目前为止,我的解决方法是使用
Modifier.graphicsLayer(translationY = -25f)
将其向上移动,但这对于本应如此简单的事情来说似乎是一个可怕的 hack。 It appears that in classic Android layouts, one could set android:includeFontPadding="false"
and that would bypass this behavior but there doesn't seem to be a similar option in Jetpack Compose.似乎在经典的 Android 布局中,可以设置
android:includeFontPadding="false"
并绕过此行为,但 Jetpack Compose 中似乎没有类似的选项。
Anyone encounter this?有人遇到过这个吗?
According to https://issuetracker.google.com/issues/171394808 , It seems this is one of the limitations of the current JetPack Compose.根据https://issuetracker.google.com/issues/171394808 ,这似乎是当前 JetPack Compose 的限制之一。
This is also deal breaker for my app because the font used rely heavily with the includeFontPadding
.这也是我的应用程序的交易破坏者,因为使用的字体严重依赖于
includeFontPadding
。 For current workaround, I create a CoreText that wraps TextView inside my compose.对于当前的解决方法,我创建了一个 CoreText,它将 TextView 包装在我的 compose 中。
Here's example of my wrapper, its not perfect but it does the job for my current use case:这是我的包装器的示例,它并不完美,但它可以满足我当前的用例:
@Composable
fun CoreText(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
overflow: TextOverflow = TextOverflow.Clip,
maxLines: Int = Int.MAX_VALUE,
style: TextStyle = Typography.body2,
onClick: (() -> Unit)? = null,
) {
AndroidView(
modifier = modifier,
factory = { context ->
TextView(context)
},
update = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
it.setTextAppearance(style.fontWeight.toStyle())
} else {
it.setTextAppearance(it.context, style.fontWeight.toStyle())
}
if (overflow == TextOverflow.Ellipsis) {
it.ellipsize = TextUtils.TruncateAt.END
}
if (textDecoration != null) {
it.paintFlags = when (textDecoration) {
TextDecoration.Underline -> {
Paint.UNDERLINE_TEXT_FLAG
}
TextDecoration.LineThrough -> {
Paint.STRIKE_THRU_TEXT_FLAG
}
else -> 0
}
}
if (onClick != null) {
it.setOnClickListener { onClick.invoke() }
}
if (color != Color.Unspecified || style.color != Color.Unspecified) {
it.setTextColor(if (color == Color.Unspecified) style.color.toArgb() else color.toArgb())
}
it.textSize = style.fontSize.value
it.text = text
it.background = ColorDrawable(style.background.toArgb())
it.maxLines = maxLines
it.includeFontPadding = false
it.textAlignment = textAlign?.toStyle() ?: style.textAlign.toStyle()
}
)
}
// Replace with your style
fun FontWeight?.toStyle(): Int {
return when (this) {
FontWeight.Bold -> R.style.TextStyle_Bold
FontWeight.Normal -> R.style.TextStyle_Regular
FontWeight.Medium, FontWeight.SemiBold -> R.style.TextStyle_Medium
else -> -1
}
}
fun TextAlign?.toStyle(): Int {
return when (this) {
TextAlign.Left -> TEXT_ALIGNMENT_TEXT_START
TextAlign.Right -> TEXT_ALIGNMENT_TEXT_END
TextAlign.Center -> TEXT_ALIGNMENT_CENTER
TextAlign.Start -> TEXT_ALIGNMENT_TEXT_START
TextAlign.End -> TEXT_ALIGNMENT_TEXT_END
else -> -1
}
}
Just got around this same issue.刚刚解决了同样的问题。
Box(contentAlignment = Alignment.Center){
Text(
text = "OK"
textAlign = TextAlign.Center
)
}
(Temporary) custom solution: (临时)定制解决方案:
fun Modifier.baselinePadding(
firstBaselineToTop: Dp,
lastBaselineToBottom: Dp
) = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
val firstBaseline = placeable[FirstBaseline]
check(placeable[LastBaseline] != AlignmentLine.Unspecified)
val lastBaseline = placeable[LastBaseline]
val lastBaselineToBottomHeight = placeable.height - lastBaseline
val lastBaselineToBottomDelta = lastBaselineToBottom.roundToPx() - lastBaselineToBottomHeight
val totalHeight = placeable.height +
(firstBaselineToTop.roundToPx() - firstBaseline)
val placeableY = totalHeight - placeable.height
layout(placeable.width, totalHeight + lastBaselineToBottomDelta) {
placeable.placeRelative(0, placeableY)
}
}
Compose now have TextStyle.platformStyle.incudeFontPadding that is set to true by default for version 1.2. Compose 现在将 TextStyle.platformStyle.incudeFontPadding 在 1.2 版中默认设置为 true。 you can set it to false in your TextStyle
您可以在 TextStyle 中将其设置为 false
Making the default false is something that Compose wants to do in v1.3 or later.将默认设置设为 false 是 Compose 在 v1.3 或更高版本中想要做的事情。
This happens due to uneven font padding on https://fonts.google.com/specimen/Oswald , plus the text you're using in lowercase makes the discrepancy more obvious.这是由于https://fonts.google.com/specimen/Oswald上的字体填充不均匀,加上您使用的小写文本使差异更加明显。
As @Siyamed mentioned below, the API to turn the default includeFontPadding behaviour off in Compose was released with Compose 1.2 beta and you use it like so:正如@Siyamed 下面提到的,API 在 Compose 中关闭默认 includeFontPadding 行为是随 Compose 1.2 beta 一起发布的,您可以像这样使用它:
Text(
...
textStyle = TextStyle(
platformStyle = PlatformTextStyle(
includeFontPadding = false
),
)
https://android-developers.googleblog.com/2022/05/whats-new-in-jetpack-compose.html https://android-developers.googleblog.com/2022/05/whats-new-in-jetpack-compose.html
give it a try, might help?试一试,可能有帮助吗?
By using Compose 1.2.0-alpha07
and above, you can use PlatformTextStyle
api to set includeFontPadding
.通过使用
Compose 1.2.0-alpha07
及以上版本,您可以使用PlatformTextStyle
api 来设置includeFontPadding
。
Try to the below code:尝试以下代码:
private val NotoSans = FontFamily(
Font(R.font.noto_san_jp_black, FontWeight.Black),
Font(R.font.noto_san_jp_light, FontWeight.Light),
Font(R.font.noto_san_jp_bold, FontWeight.Bold),
Font(R.font.noto_san_jp_thin, FontWeight.Thin),
Font(R.font.noto_san_jp_medium, FontWeight.Medium),
Font(R.font.noto_san_jp_regular, FontWeight.Normal),
)
val Typography = Typography(
headlineLarge = Typography().headlineLarge.copy(
fontFamily = NotoSans,
)
)
@OptIn(ExperimentalTextApi::class)
/* ... */
Text(
text = "地域のお得は\nすべてここに",
style = MaterialTheme.typography.headlineLarge.copy(
platformStyle = PlatformTextStyle(
includeFontPadding = false
)
/* ... */
)
)
The result when includeFontPadding = false
: includeFontPadding = false
时的结果:
The result when includeFontPadding = true
or no using it: includeFontPadding = true
或不使用时的结果:
More information:更多信息:
Fixing Font Padding in Compose Text - Medium 修复撰写文本中的字体填充 - Medium
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.