Jetpack Compose 动态字号圆形自定义Badge绘制异常如何解决?
Jetpack Compose 动态尺寸Badge实现方案
你需要的效果可以通过Text的onTextLayout回调配合动态形状实现,无需自定义Layout,性能更高,实现逻辑更简单:
@Composable fun DynamicBadge( text: String, modifier: Modifier = Modifier, fontSize: TextUnit = 14.sp, textColor: Color = Color.White, badgeColor: Color = Color.Red, horizontalPadding: Dp = 8.dp, verticalPadding: Dp = 2.dp ) { val density = LocalDensity.current // 存储文本测量后的实际尺寸 var textRawSize by remember { mutableStateOf(IntSize.Zero) } // 根据文本尺寸动态计算形状 val badgeShape = remember(textRawSize, density) { val textWidth = with(density) { textRawSize.width.toDp() } val textHeight = with(density) { textRawSize.height.toDp() } // 文本加水平内边距后宽高相等则用正圆,否则用50%圆角的胶囊形状 val finalWidth = textWidth + horizontalPadding * 2 val finalHeight = textHeight + verticalPadding * 2 if (finalWidth <= finalHeight) CircleShape else RoundedCornerShape(50) } Text( text = text, fontSize = fontSize, color = textColor, textAlign = TextAlign.Center, modifier = modifier .onTextLayout { textRawSize = it.size } .padding(horizontal = horizontalPadding, vertical = verticalPadding) .background( color = badgeColor, shape = badgeShape ) ) }
实现说明
- 首次测量文本尺寸后会自动计算匹配的形状,1位数字加完内边距后宽高一致,自动呈现正圆,多位数字宽度大于高度时自动切换为胶囊圆角,完全符合需求
- 仅在文本内容变化时触发重新测量,无多余重组,性能开销极低
- 文本默认居中对齐,无需额外处理偏移
- 支持自定义字体大小、内边距、配色等参数,适配性更强
测试示例
Column( modifier = Modifier.padding(32.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { // 1位数字,显示正圆 DynamicBadge(text = "5", fontSize = 34.sp) // 2位数字,显示胶囊圆角 DynamicBadge(text = "24", fontSize = 34.sp) // 多位文本,自动适配宽度 DynamicBadge(text = "999+", fontSize = 24.sp) }
内容的提问来源于stack exchange,提问作者Thracian
相关产品推荐
相关产品推荐

