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

如何在SwiftUI中实现起始值为3英尺的范围滑块

修改Range Slider以3英尺为起始值的方案

要让你的Range Slider从3英尺(36英寸)开始,只需调整高度数值的映射逻辑并修正初始值设置,具体修改如下:

核心修改步骤

1. 新增基础起始高度常量

在HeightRangeSliderView中添加表示3英尺的英寸常量,作为高度计算的基准:

private let baseHeightInInches = 36.0 // 3英尺 = 36英寸

2. 调整高度数值计算逻辑

原来的代码将滑块位置直接映射为0-100英寸,现在改为从36英寸(3ft)开始累加,修改heightMinValue和heightMaxValue的计算:

var heightMinValue: Measurement<UnitLength> {
    Measurement(value: baseHeightInInches + (scaleMinValue / barWidth) * 100, unit: UnitLength.inches)
}
var heightMaxValue: Measurement<UnitLength> {
    Measurement(value: baseHeightInInches + (scaleMaxValue / barWidth) * 100, unit: UnitLength.inches)
}

3. 设置初始值为3英尺对应的滑块位置

在ContentView中,将heightMinValue初始值改为0(滑块最左端,对应3ft),同时可按需调整heightMaxValue的初始位置:

@State var heightMinValue: Double = 0 // 滑块最左端,对应3英尺
@State var heightMaxValue: Double = 0.6 * Constants.Range.size // 示例:对应8英尺(3ft+60英寸)

修改后的完整代码

import SwiftUI

struct ContentView: View {
    @State var heightMinValue: Double = 0 // 初始为滑块最左端,对应3英尺
    @State var heightMaxValue: Double = 0.6 * Constants.Range.size // 初始对应8英尺(3ft+60英寸)
    var body: some View {
        VStack {
            HeightRangeSliderView(scaleMinValue: $heightMinValue, scaleMaxValue: $heightMaxValue, minimumpercentageVal: 0, lableWidth: 89)
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct HeightRangeSliderView: View {
    /// Slider绑定的最小/最大值
    @Binding var scaleMinValue: Double
    @Binding var scaleMaxValue: Double
    var minimumpercentageVal: Double
    var leftKnobWidth: Double = 28
    var leftKnobHeight: Double = 28
    var rightKnobWidth: Double = 28
    var rightKnobHeight: Double = 28
    var barWidth: Double = Constants.Range.size
    var leftKnobColor = Color.white
    var rightKnobColor = Color.white
    var backgroundTrackColor = Color.DesignSystem.Divider
    var selectedTrackColor = Color.DesignSystem.Active
    /// 滑块最小/最大值标签颜色
    var sliderMinMaxValuesColor = Color.DesignSystem.Active
    /// 滑块标签尺寸
    var lableWidth: Double = 55
    var lableColor = Color.DesignSystem.FieldBg
    
    // 基础起始高度:3英尺 = 36英寸
    private let baseHeightInInches = 36.0
    private let heightformatStyle = Measurement<UnitLength>.FormatStyle(width: .abbreviated, usage: .personHeight)
    
    var heightMinValue: Measurement<UnitLength> {
        Measurement(value: baseHeightInInches + (scaleMinValue / barWidth) * 100, unit: UnitLength.inches)
    }
    var heightMaxValue: Measurement<UnitLength> {
        Measurement(value: baseHeightInInches + (scaleMaxValue / barWidth) * 100, unit: UnitLength.inches)
    }
    
    var body: some View {
        VStack {
            /// 滑块当前最小/最大值显示
            HStack {
                Text(heightMinValue, format: heightformatStyle)
                    .monospacedDigit()
                    .frame(width: lableWidth, height: 40, alignment: .center)
                    .foregroundColor(sliderMinMaxValuesColor)
                    .background(lableColor, in: RoundedRectangle(cornerRadius: 8))
                Spacer()
                Text(heightMaxValue, format: heightformatStyle)
                    .monospacedDigit()
                    .frame(width: lableWidth, height: 40, alignment: .center)
                    .foregroundColor(sliderMinMaxValuesColor)
                    .background(lableColor, in: RoundedRectangle(cornerRadius: 8))
            }
            .frame(width: (barWidth + (rightKnobWidth * 2)))
            .padding(.horizontal)
            
            /// 滑块轨道视图
            ZStack(alignment: .leading) {
                // 背景轨道
                Capsule()
                    .fill(backgroundTrackColor)
                    .frame(width: (barWidth + (rightKnobWidth * 2)), height: 6)
                
                // 选中的轨道
                Capsule()
                    .fill(selectedTrackColor)
                    .frame(width: scaleMaxValue - scaleMinValue, height: 6)
                    .offset(x: scaleMinValue + rightKnobWidth)
                
                HStack(spacing: 0) {
                    // 左旋钮
                    Circle()
                        .fill(leftKnobColor)
                        .shadow(color: Color.black.opacity(0.2), radius: 12, x: 0, y: 6)
                        .shadow(color: Color.black.opacity(0.2), radius: 4, x: 0, y: 0.5)
                        .frame(width: leftKnobWidth, height: leftKnobHeight)
                        .offset(x: scaleMinValue)
                        .gesture(DragGesture().onChanged({ value in
                            // 拖拽边界限制:左旋钮不能超过右旋钮,且不能小于0
                            if value.location.x >= 0 && value.location.x <= scaleMaxValue {
                                scaleMinValue = value.location.x
                            }
                        }))
                    
                    // 右旋钮
                    Circle()
                        .fill(rightKnobColor)
                        .shadow(color: Color.black.opacity(0.2), radius: 12, x: 0, y: 6)
                        .shadow(color: Color.black.opacity(0.2), radius: 4, x: 0, y: 0.5)
                        .frame(width: rightKnobWidth, height: rightKnobHeight)
                        .offset(x: scaleMaxValue)
                        .gesture(DragGesture().onChanged({ value in
                            // 拖拽边界限制:右旋钮不能超过轨道长度,且不能小于左旋钮
                            if value.location.x <= barWidth && value.location.x >= scaleMinValue {
                                scaleMaxValue = value.location.x
                            }
                        }))
                }
            }
        }
    }
}

enum Constants {
    enum Range {
        static let size = UIScreen.main.bounds.width - 100
    }
}

extension Color {
    enum DesignSystem {
        public static let Active = Color.green
        public static let FieldBg = Color.black
        public static let Divider = Color.gray
    }
}

效果说明

修改后:

  • 滑块左旋钮最左端对应3英尺(3ft),完全符合需求
  • 滑块位置比例将转换为从3ft开始的高度(比如滑块拉到中间时,显示3ft+50英寸=7ft2)
  • 拖拽逻辑保持原有边界限制,确保左旋钮不会超过右旋钮,右旋钮不会超出轨道范围

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:28:08