如何让drawArc绘制的圆弧两端朝同一方向弯曲?
解决Jetpack Compose drawArc 两端同向圆角问题
Jetpack Compose 的 drawArc 搭配 StrokeCap.Round 时,圆角是沿着圆弧切线方向生成的,所以两端圆角方向自然相反。目前没有直接的API可以实现两端同向弯曲的效果,需要手动绘制两端的圆角,以下是具体实现方案:
实现步骤
- 先绘制不带圆角的基础圆弧(用
StrokeCap.Butt避免默认圆角) - 计算圆弧两端的半圆圆心(根据需求朝向圆弧外侧或内侧)
- 在两端分别绘制半圆,实现同向圆角效果
代码示例
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
相关产品推荐
相关产品推荐

