Jetpack Compose如何实现仅单侧带圆角的线条?
在Jetpack Compose中绘制单侧圆角线条的优雅实现
由于drawLine的cap参数会同时作用于线条两端,无法单独指定单侧圆角,这里推荐两种简洁的实现方式,完美适配你需要的双色进度条场景:
方法一:使用drawRoundRect模拟单侧圆角线条
这是最直接优雅的方案,利用drawRoundRect可以单独控制四个角圆角半径的特性,只给线条的一端设置圆角,另一端设为0。
封装单侧圆角绘制函数
// 绘制左圆角、右平直的线条 fun DrawScope.drawLeftRoundedLine( color: Color, start: Offset, end: Offset, strokeWidth: Float ) { val halfStroke = strokeWidth / 2f // 构建覆盖线条区域的矩形,确保线条居中于start-end路径 val lineRect = Rect( left = start.x, top = start.y - halfStroke, right = end.x, bottom = start.y + halfStroke ) drawRoundRect( color = color, topLeft = lineRect.topLeft, bottomRight = lineRect.bottomRight, // 仅左上角、左下角设置圆角,右上角、右下角为0 cornerRadius = CornerRadius(halfStroke, 0f) ) } // 绘制右圆角、左平直的线条 fun DrawScope.drawRightRoundedLine( color: Color, start: Offset, end: Offset, strokeWidth: Float ) { val halfStroke = strokeWidth / 2f val lineRect = Rect( left = start.x, top = start.y - halfStroke, right = end.x, bottom = start.y + halfStroke ) drawRoundRect( color = color, topLeft = lineRect.topLeft, bottomRight = lineRect.bottomRight, // 仅右上角、右下角设置圆角,左上角、左下角为0 cornerRadius = CornerRadius(0f, halfStroke) ) }
双色进度条实战示例
@Composable fun RoundedProgressBar( progress: Float, // 取值范围0f~1f strokeWidth: Dp = 8.dp, backgroundColor: Color = Color.Gray, progressColor: Color = Color.Blue ) { Canvas( modifier = Modifier .fillMaxWidth() .height(strokeWidth) ) { val strokePx = strokeWidth.toPx() val centerY = size.height / 2f val totalWidth = size.width val progressWidth = totalWidth * progress.coerceIn(0f, 1f) // 绘制背景条:左平直、右圆角 drawRightRoundedLine( color = backgroundColor, start = Offset(0f, centerY), end = Offset(totalWidth, centerY), strokeWidth = strokePx ) // 绘制进度条:左圆角、右平直(与背景交接处无圆角) if (progressWidth > 0) { drawLeftRoundedLine( color = progressColor, start = Offset(0f, centerY), end = Offset(progressWidth, centerY), strokeWidth = strokePx ) } } } // 使用示例 @Composable fun ProgressDemo() { Column(modifier = Modifier.padding(16.dp)) { RoundedProgressBar(progress = 0.6f) } }
方法二:使用drawPath拼接线段与圆弧
如果需要更灵活的路径控制,可以用Path手动拼接圆角弧和直线:
fun DrawScope.drawLeftRoundedLinePath( color: Color, start: Offset, end: Offset, strokeWidth: Float ) { val halfStroke = strokeWidth / 2f val path = Path().apply { // 从右下角开始,画直线到右上角 moveTo(start.x, start.y + halfStroke) lineTo(end.x, start.y + halfStroke) // 画右上角到左上角的直线 lineTo(end.x, start.y - halfStroke) // 画左上角到左下角的圆弧(形成左圆角) arcTo( rect = Rect( start.x - halfStroke, start.y - halfStroke, start.x + halfStroke, start.y + halfStroke ), startAngleDegrees = 90f, sweepAngleDegrees = 180f, forceMoveTo = false ) close() } drawPath(path = path, color = color) }
不过这种方式代码相对繁琐,推荐优先使用drawRoundRect方案。
内容的提问来源于stack exchange,提问作者Johan Paul
相关产品推荐
相关产品推荐

