SwiftUI中如何实现仅顺时针末端圆角的圆形进度条?
实现仅进度末端保留圆角的圆形进度视图
要解决你遇到的「设置lineCap: .round后两端均为圆角,仅需末端(非100%进度时)保留圆角」的问题,可以通过主体平角进度条+末端圆点的组合方式实现,既简单又能精准控制样式:
修改后的完整代码
struct SpeedometerView: View { // 可自定义进度值(范围0~1) var progress: CGFloat = 0.2 private let lineWidth: CGFloat = 4 var body: some View { ZStack { Color.black.edgesIgnoringSafeArea(.all) speedProgressView(width: 300) } } private func speedProgressView(width: CGFloat) -> some View { let dotSize = lineWidth ZStack { // 1. 主体进度条:两端均为平角 Circle() .trim(from: 0, to: progress) .stroke(.red, style: StrokeStyle(lineWidth: lineWidth, lineCap: .butt)) .shadow(color: .green, radius: 10) .shadow(color: .green, radius: 2) // 2. 末端圆角圆点:仅进度非100%时显示 if progress < 1.0 { Circle() .fill(.red) .shadow(color: .green, radius: 10) .shadow(color: .green, radius: 2) .frame(width: dotSize, height: dotSize) // 偏移到进度条末端的圆周位置 .offset(x: (width / 2) - (lineWidth / 2)) // 旋转到进度对应的角度(适配trim的进度范围) .rotationEffect(.degrees(progress * 360 - 90)) } } .frame(width: width) .rotationEffect(.degrees(100)) } } #Preview { SpeedometerView() }
核心思路说明
- 主体进度条:将
lineCap改为.butt,强制两端为平角,避免起始端出现圆角; - 末端圆点:用一个直径等于线条宽度的圆形,模拟
lineCap: .round的末端圆角效果,并且仅在进度未达到100%时显示(避免100%时圆点与起始端重叠); - 位置校准:通过
offset将圆点定位到进度条的圆周路径上,再用rotationEffect根据进度值计算旋转角度,确保圆点始终对齐进度末端; - 视觉统一:给圆点添加与主体进度条一致的阴影效果,保证整体样式协调。
这种方法比直接使用lineCap更灵活,能完全满足你对两端样式的差异化需求。
内容的提问来源于stack exchange,提问作者batman
相关产品推荐
相关产品推荐

