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

如何让drawArc绘制的圆弧两端朝同一方向弯曲?

解决Jetpack Compose drawArc 两端同向圆角问题

Jetpack Compose 的 drawArc 搭配 StrokeCap.Round 时,圆角是沿着圆弧切线方向生成的,所以两端圆角方向自然相反。目前没有直接的API可以实现两端同向弯曲的效果,需要手动绘制两端的圆角,以下是具体实现方案:

实现步骤

  1. 先绘制不带圆角的基础圆弧(用 StrokeCap.Butt 避免默认圆角)
  2. 计算圆弧两端的半圆圆心(根据需求朝向圆弧外侧或内侧)
  3. 在两端分别绘制半圆,实现同向圆角效果

代码示例

Canvas(modifier = Modifier.size(250.dp)) {
    val strokeWidth = 20.dp.toPx()
    val arcRadius = 100.dp.toPx()
    val center = Offset(size.width / 2, size.height / 2)
    val startAngle = 180f
    val sweepAngle = 90f

    // 1. 绘制基础圆弧(无默认圆角)
    drawArc(
        color = Color.Blue,
        startAngle = startAngle,
        sweepAngle = sweepAngle,
        useCenter = false,
        topLeft = Offset(center.x - arcRadius, center.y - arcRadius),
        size = Size(arcRadius * 2, arcRadius * 2),
        style = Stroke(width = strokeWidth, cap = StrokeCap.Butt)
    )

    // 2. 计算起始端半圆的圆心
    val startAngleRad = Math.toRadians(startAngle.toDouble()).toFloat()
    val startPoint = Offset(
        center.x + arcRadius * cos(startAngleRad),
        center.y + arcRadius * sin(startAngleRad)
    )
    // 朝向圆弧外侧(若要内侧,将 +90f 改为 -90f)
    val startCapDirectionAngle = startAngle + 90f
    val startCapCenter = startPoint + Offset(
        (strokeWidth / 2) * cos(Math.toRadians(startCapDirectionAngle.toDouble()).toFloat()),
        (strokeWidth / 2) * sin(Math.toRadians(startCapDirectionAngle.toDouble()).toFloat())
    )

    // 3. 计算结束端半圆的圆心
    val endAngle = startAngle + sweepAngle
    val endAngleRad = Math.toRadians(endAngle.toDouble()).toFloat()
    val endPoint = Offset(
        center.x + arcRadius * cos(endAngleRad),
        center.y + arcRadius * sin(endAngleRad)
    )
    val endCapDirectionAngle = endAngle + 90f
    val endCapCenter = endPoint + Offset(
        (strokeWidth / 2) * cos(Math.toRadians(endCapDirectionAngle.toDouble()).toFloat()),
        (strokeWidth / 2) * sin(Math.toRadians(endCapDirectionAngle.toDouble()).toFloat())
    )

    // 4. 绘制两端的半圆
    // 起始端半圆
    drawArc(
        color = Color.Blue,
        startAngle = startCapDirectionAngle - 180f,
        sweepAngle = 180f,
        useCenter = true,
        topLeft = Offset(startCapCenter.x - strokeWidth / 2, startCapCenter.y - strokeWidth / 2),
        size = Size(strokeWidth, strokeWidth)
    )
    // 结束端半圆
    drawArc(
        color = Color.Blue,
        startAngle = endCapDirectionAngle - 180f,
        sweepAngle = 180f,
        useCenter = true,
        topLeft = Offset(endCapCenter.x - strokeWidth / 2, endCapCenter.y - strokeWidth / 2),
        size = Size(strokeWidth, strokeWidth)
    )
}

说明

  • 如果需要圆角朝向圆弧内侧,只需将计算圆心时的 +90f 改为 -90f 即可
  • 半圆的半径等于圆弧线宽的一半,保证和基础圆弧的线宽匹配

内容的提问来源于stack exchange,提问作者oop

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:45:27