Jetpack Compose Text如何实现类似Telegram的包裹子串批量加粗功能
Jetpack Compose 自定义Text实现
**包裹内容加粗效果 原实现问题
- 正则使用贪心匹配
.*,会匹配从第一个**到最后一个**之间的所有内容,无法正确拆分多组独立的加粗片段 - 仅调用一次
find()只能获取第一个匹配结果,不支持多组加粗片段渲染 - 全局替换所有
**字符,会误删不合法、不成对的标记,不符合测试用例要求 - 加粗样式的位置基于原始字符串计算,全局删除
**后字符串长度变短,导致样式位置错位
修正方案
- 调整正则规则,匹配成对
**包裹、且中间无连续*的非空内容,避免匹配非法格式 - 遍历所有合法匹配结果,直接在构建
AnnotatedString的过程中分段处理普通文本和加粗文本,不需要提前修改原字符串,避免位置偏移问题 - 不合法、不成对的
**标记会原样保留,不做任何处理
完整实现代码
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp // 加粗匹配正则:匹配成对**包裹、中间无连续*的非空内容 private val boldRegex = Regex("\\*\\*([^*]*(?:\\*[^*]+)*)\\*\\*") @Composable fun CustomText(text: String, modifier: Modifier = Modifier) { val annotatedString = buildAnnotatedString { var currentProcessPos = 0 // 查找所有合法匹配 val allMatches = boldRegex.findAll(text) allMatches.forEach { matchResult -> // 取出加粗内容,空内容直接跳过 val boldContent = matchResult.groupValues[1].takeIf { it.isNotEmpty() } ?: return@forEach // 追加当前匹配之前的普通文本 append(text.substring(currentProcessPos, matchResult.range.first)) // 追加带加粗样式的内容 withStyle( style = SpanStyle( fontWeight = FontWeight.Bold, color = Color(0xff64B5F6), fontSize = 15.sp ) ) { append(boldContent) } // 更新处理位置到当前匹配的结束下标 currentProcessPos = matchResult.range.last + 1 } // 追加最后一段剩余的普通文本 append(text.substring(currentProcessPos)) } Text( modifier = modifier .fillMaxWidth() .padding(horizontal = 8.dp, vertical = 12.dp), fontSize = 16.sp, text = annotatedString ) }
效果验证
上述实现完全符合你给出的4条测试用例预期:
- 单组成对
**包裹的内容正常加粗,标记被移除 - 多组成对
**包裹的内容分别加粗,标记被移除,剩余单个*原样保留 - 非法格式的
**组合无匹配,所有内容原样保留,无样式修改 - 无闭合的
**标记无匹配,所有内容原样保留,无样式修改
内容的提问来源于stack exchange,提问作者Thracian
相关产品推荐
相关产品推荐

