SwiftUI实现带刻度线与虚线框的双垂直进度条技术求助
SwiftUI垂直进度条优化:基于最大重量动态调整组件位置
我在SwiftUI中开发带刻度线和虚线框的垂直进度条时,遇到了ZStack布局下组件偏移固定值导致适配性差的问题。需要新增最大重量属性,通过重量与最大重量的比例动态计算Y轴偏移,让刻度线和虚线框对应正确的位置。
修改后的实现代码
import SwiftUI struct LoadManagementItemBarView: View { let isLeft: Bool let userWeight: Float let maxWeight: Float // 新增最大重量参数,用于动态计算位置比例 @State var progress: CGFloat // 计算用户重量在进度条中的比例(底部为0kg,顶部为maxWeight) private var weightOffsetRatio: CGFloat { CGFloat(userWeight / maxWeight) } // 提取固定常量,便于后续维护 private let barTotalHeight: CGFloat = 490 private let dashedBoxHeight: CGFloat = 188 var body: some View { ZStack(alignment: .bottom) { // 进度条背景 Rectangle() .fill(Color.white) .frame(width: 32, height: barTotalHeight) // 进度填充部分 Rectangle() .fill(Color.positiveStappone) .frame(width: 32, height: progress) VStack(spacing: 0) { // 用户重量刻度线 HStack(alignment: .center) { if isLeft { Text("\(String(format: "%.0f", userWeight)) kg") } Rectangle() .frame(width: 38, height: 1) if !isLeft { Text("\(String(format: "%.0f", userWeight)) kg") } } .offset(y: -weightOffsetRatio * barTotalHeight) // 基于比例动态偏移 // 动态定位的虚线框 Rectangle() .strokeBorder(style: StrokeStyle(lineWidth: 1, dash: [10])) .frame(width: 32, height: dashedBoxHeight) .offset( x: isLeft ? 24 : -23, y: -(weightOffsetRatio * barTotalHeight) - dashedBoxHeight / 2 ) // 0kg刻度线 HStack(alignment: .center) { if isLeft { Text(" 0 kg") } Rectangle() .frame(width: 38, height: 1) if !isLeft { Text(" 0 kg") } } } .offset(x: isLeft ? -24 : 23) } .shadow(color: .gray, radius: 1, x: 1, y: 1) } } struct LoadManagementItemBarView_Previews: PreviewProvider { static var previews: some View { LoadManagementItemBarView( isLeft: true, userWeight: 76, maxWeight: 150, // 传入示例最大重量值 progress: 350 ) } }
核心优化点
- 新增
maxWeight参数:作为重量刻度的上限,彻底替代固定偏移值,适配不同重量范围的场景 - 比例化偏移计算:通过
weightOffsetRatio将重量转换为进度条高度的比例,确保刻度线和虚线框位置始终对应实际重量 - 虚线框居中对齐:基于用户重量位置和自身高度计算偏移,让虚线框精准覆盖用户重量对应的进度条区域
- 常量提取:把进度条高度、虚线框高度等固定值提取为私有常量,提升代码可维护性
内容的提问来源于stack exchange,提问作者David Edson
相关产品推荐
相关产品推荐

