Android Jetpack Compose 如何为Box添加带文本打断的局部边框效果
要实现带缺口的局部边框效果,因为后续背景要替换为图片,不能用色块遮挡边框伪造缺口,所以直接自定义绘制边框即可,具体实现如下:
步骤1:自定义带缺口的圆角边框修饰符
我们通过drawBehind手动绘制边框路径,在左下角预留对应文本宽度的缺口:
fun Modifier.notchedRoundedBorder( borderWidth: Dp, borderColor: Color, cornerRadius: Dp, notchWidth: Dp, notchPadding: Dp = 8.dp // 缺口与文本的左右留白 ) = this.then( Modifier.drawBehind { val borderPx = borderWidth.toPx() val cornerPx = cornerRadius.toPx() val notchTotalWidth = notchWidth.toPx() + notchPadding.toPx() * 2 val borderPath = Path().apply { // 从左下角缺口右端点开始绘制 moveTo(notchTotalWidth, size.height - cornerPx) // 左下角圆角 arcTo( rect = Rect(0f, size.height - cornerPx * 2, cornerPx * 2, size.height), startAngleDegrees = 90f, sweepAngleDegrees = 90f, forceMoveTo = false ) // 底部边框到右下角圆角 lineTo(size.width - cornerPx, size.height) // 右下角圆角 arcTo( rect = Rect(size.width - cornerPx * 2, size.height - cornerPx * 2, size.width, size.height), startAngleDegrees = 0f, sweepAngleDegrees = -90f, forceMoveTo = false ) // 右侧边框到右上角圆角 lineTo(size.width, cornerPx) // 右上角圆角 arcTo( rect = Rect(size.width - cornerPx * 2, 0f, size.width, cornerPx * 2), startAngleDegrees = 270f, sweepAngleDegrees = -90f, forceMoveTo = false ) // 顶部边框到左上角圆角 lineTo(cornerPx, 0f) // 左上角圆角 arcTo( rect = Rect(0f, 0f, cornerPx * 2, cornerPx * 2), startAngleDegrees = 180f, sweepAngleDegrees = -90f, forceMoveTo = false ) // 左侧边框到缺口左端点停止,留空缺口 lineTo(0f, size.height - cornerPx * 2) } drawPath( path = borderPath, color = borderColor, style = Stroke(width = borderPx) ) } )
步骤2:替换原有布局的border修饰符
先测量文本宽度用来匹配缺口大小,再替换原有边框逻辑:
@Composable fun NotchedBorderScreen() { val displayText = "this is Test" // 测量文本宽度,自动适配缺口大小 val textPaint = remember { Paint().apply { textSize = 14.sp.toPx() } } val textWidth = textPaint.measureText(displayText).toDp() Box( modifier = Modifier .fillMaxWidth() .fillMaxHeight() ) { // 背景层,后续直接替换为Image组件即可 Box( modifier = Modifier .fillMaxSize() .background(Color(0xFF37C7D7).copy(alpha = 0.6f)) ) // 外层带缺口边框 Box( modifier = Modifier .fillMaxSize() .padding(20.dp, 30.dp) .notchedRoundedBorder( borderWidth = 0.8.dp, borderColor = Color.White.copy(alpha = 0.5f), cornerRadius = 32.dp, notchWidth = textWidth ) ) // 内层带缺口边框 Box( modifier = Modifier .fillMaxSize() .padding(28.dp, 38.dp) .notchedRoundedBorder( borderWidth = 0.8.dp, borderColor = Color.White.copy(alpha = 0.5f), cornerRadius = 28.dp, notchWidth = textWidth ) ) // 文本层,放在缺口位置 Column( modifier = Modifier .statusBarsPadding() .fillMaxSize() .padding(20.dp, 40.dp), verticalArrangement = Arrangement.Bottom ) { Text( text = displayText, modifier = Modifier.padding(8.dp, 30.dp), color = Color.White, fontSize = 14.sp ) } } }
该方案完全没有用背景遮挡边框,后续替换背景为图片不会有任何适配问题,所有圆角、边框样式都和你原有代码保持一致,仅移除了左下角对应文本长度的边框段。如果需要调整缺口位置或者大小,直接修改notchedRoundedBorder的参数即可。
内容的提问来源于stack exchange,提问作者Ankit Shah
相关产品推荐
相关产品推荐

