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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:18:15