You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:17:43