Jetpack Compose中实现AutoSizeText自适应文字大小
时间:2026-08-21 | 作者:极客少年 | 阅读:0使用二分查找法实现Text的字体大小自适应,代码如下:
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
@Composable
fun AutoSizeText(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontStyle: FontStyle = null,
fontWeight: FontWeight = null,
fontFamily: FontFamily = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration = null,
textAlign: TextAlign = TextAlign.Unspecified,
lineHeight: TextUnit = TextUnit.Unspecified,
maxLines: Int = 1,
overflow: TextOverflow = TextOverflow.Ellipsis,
onTextLayout: ((TextLayoutResult) -> Unit) = null,
style: TextStyle = LocalTextStyle.current.copy(
color = color,
fontStyle = fontStyle,
fontWeight = fontWeight,
fontFamily = fontFamily,
letterSpacing = letterSpacing,
textDecoration = textDecoration,
textAlign = textAlign,
lineHeight = lineHeight,
),
maxFontSize: TextUnit = 100.sp,
minFontSize: TextUnit = 10.sp,
) {
val textMeasurer = rememberTextMeasurer()
BoxWithConstraints(modifier = modifier) {
// 1. 获取容器的约束尺寸
val maxWidthPx = constraints.maxWidth
val maxHeightPx = constraints.maxHeight
// 2. 使用 remember 缓存计算结果,只有 text 或约束改变时才重新计算
val optimizedFontSize = remember(text, maxWidthPx, maxHeightPx) {
var low = minFontSize.value
var high = maxFontSize.value
var res = low
// 二分查找循环
while (low <= high) {
val mid = (low + high) / 2
val isFit = checkTextFit(
textMeasurer = textMeasurer,
text = text,
fontSize = mid.sp,
style = style,
maxWidthPx = maxWidthPx,
maxHeightPx = maxHeightPx,
maxLines = maxLines
)
if (isFit) {
res = mid
low = mid + 0.5f // 尝试更大的字号(步长可调)
} else {
high = mid - 0.5f // 字号太大了,调小一点
}
}
res.sp
}
// 3. 最终渲染
Text(
text = text,
color = color,
fontSize = optimizedFontSize,
style = style,
maxLines = maxLines,
overflow = overflow,
onTextLayout = onTextLayout
)
}
}
/**
* 核心辅助函数:使用 TextMeasurer 在内存中测量文字是否溢出
*/
private fun checkTextFit(
textMeasurer: TextMeasurer,
text: String,
fontSize: TextUnit,
style: TextStyle,
maxWidthPx: Int,
maxHeightPx: Int,
maxLines: Int
): Boolean {
val layoutResult = textMeasurer.measure(
text = AnnotatedString(text),
style = style.copy(fontSize = fontSize),
maxLines = maxLines,
constraints = Constraints(maxWidth = maxWidthPx, maxHeight = maxHeightPx)
)
// 同时检查宽度和高度是否在容器范围内
return layoutResult.size.width < maxWidthPx && layoutResult.size.height < maxHeightPx
}
以上是完整代码,可直接使用。
简单分析
核心逻辑在于:通过checkTextFit方法判断文字是否超出容器范围。
如果超出了,就执行
high = mid - 0.5f,表示把字号调小一点。如果没有超出,就执行
low = mid + 0.5f,表示继续尝试更大的字号。这里的步长是可以调整的。
整个过程会持续循环,直到low > high。
当循环结束后,得到的res就是自适应的字体大小。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- Kotlin基础语法:从包定义到函数声明的核心指南
- 时间:2026-08-27
-
- 协程进阶:协作、互斥与共享状态管理
- 时间:2026-08-27
-
- Kotlin 协程快速入门:核心定义、特性与实战指南
- 时间:2026-08-27
-
- Kotlin If表达式:告别嵌套,实现简洁赋值
- 时间:2026-08-27
-
- Kotlin流程控制精讲:for循环与区间(Range)的优雅结合
- 时间:2026-08-27
-
- Kotlin 流程控制:while 与 do/while 循环详解
- 时间:2026-08-27
-
- Kotlin/Js For Harmony:ArkTs开发工具套件详解
- 时间:2026-08-27
-
- Kotlin 类基础:深入解析主构造函数与次构造函数
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
