[英]Jetpack Compose, centering text without font padding?
我在 Jetpack Compose alpha-11 版中遇到垂直居中文本問題。 看來我的字體有大量填充,我無法找到禁用它的方法。 據我所知, 這在 SO 之前只出現過一次,但是他們對使用約束布局的回答似乎表明他們只是將其絕對定位,這與其說是一種解決方案,不如說是一種解決方案,和我想避免的事情。
您可以在下面的屏幕截圖中清楚地看到它。
代碼如下所示:
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)
)
}
您期望的 arguments 到 position 它 -- verticalArrangement
和textAlign
-- 在這里不執行任何操作,但我將它們包括在內以演示我的嘗試。
到目前為止,我的解決方法是使用Modifier.graphicsLayer(translationY = -25f)
將其向上移動,但這對於本應如此簡單的事情來說似乎是一個可怕的 hack。 似乎在經典的 Android 布局中,可以設置android:includeFontPadding="false"
並繞過此行為,但 Jetpack Compose 中似乎沒有類似的選項。
有人遇到過這個嗎?
根據https://issuetracker.google.com/issues/171394808 ,這似乎是當前 JetPack Compose 的限制之一。
這也是我的應用程序的交易破壞者,因為使用的字體嚴重依賴於includeFontPadding
。 對於當前的解決方法,我創建了一個 CoreText,它將 TextView 包裝在我的 compose 中。
這是我的包裝器的示例,它並不完美,但它可以滿足我當前的用例:
@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
}
}
剛剛解決了同樣的問題。
Box(contentAlignment = Alignment.Center){
Text(
text = "OK"
textAlign = TextAlign.Center
)
}
(臨時)定制解決方案:
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 現在將 TextStyle.platformStyle.incudeFontPadding 在 1.2 版中默認設置為 true。 您可以在 TextStyle 中將其設置為 false
將默認設置設為 false 是 Compose 在 v1.3 或更高版本中想要做的事情。
這是由於https://fonts.google.com/specimen/Oswald上的字體填充不均勻,加上您使用的小寫文本使差異更加明顯。
正如@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
試一試,可能有幫助嗎?
通過使用Compose 1.2.0-alpha07
及以上版本,您可以使用PlatformTextStyle
api 來設置includeFontPadding
。
嘗試以下代碼:
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
)
/* ... */
)
)
includeFontPadding = false
時的結果:
includeFontPadding = true
或不使用時的結果:
更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.