我正在制作使用流体音量的东西,并想让它同时适用于使用英制和公制的用户.
我目前在将滑块上的公制转换为英制时遇到了问题,ClosedRange
的最大值是错误的.
我不完全确定我错在哪里,但我也不确定这是否是处理它的最好方法.
我的 idea 是将一切都存储在公制中,对于那些想要为他们转换用户界面的用户来说--因为公制是我的主要衡量标准(对我来说更容易阅读).
这是我使用的测试代码:
struct SettingsMenu: View {
private let types: [UnitVolume] = [.milliliters, .fluidOunces]
@State private var selectedUnitVolume: UnitVolume = .milliliters
@State private var selectedGoal: Double = 2000
var body: some View {
Form {
Section {
Picker("Measurement unit", selection: $selectedUnitVolume) {
ForEach(types, id: \.self) { type in
Text(type.symbol).tag(type)
}
}
.onChange(of: selectedUnitVolume) { _, newUnit in
if newUnit == .milliliters {
selectedGoal = Measurement(value: selectedGoal, unit: UnitVolume.fluidOunces).converted(to: .milliliters).value
} else {
selectedGoal = Measurement(value: selectedGoal, unit: UnitVolume.milliliters).converted(to: .fluidOunces).value
}
}
VStack(alignment: .leading) {
Label(label, systemImage: "drop.fill")
Slider(value: $selectedGoal, in: range, step: step) {
Text("Drink goal")
} minimumValueLabel: {
Text("\(Int(range.lowerBound))")
.font(.footnote)
.foregroundStyle(.gray)
} maximumValueLabel: {
Text("\(Int(range.upperBound))")
.font(.footnote)
.foregroundStyle(.gray)
}
}
}
}
}
var range: ClosedRange<Double> {
selectedUnitVolume == .milliliters ? 100...5000 : 3...175
}
var step: Double {
selectedUnitVolume == .milliliters ? 50 : 1
}
var label: String {
let value = selectedUnitVolume == .milliliters ? selectedGoal : Measurement(value: selectedGoal, unit: UnitVolume.milliliters).converted(to: .fluidOunces).value.rounded()
return "Daily saving goal: \(value.formatted(.number)) \(selectedUnitVolume.symbol)"
}
}
这导致了以下结果:
如您所见,单元中的switch 确实更新了滑块的最小/最大值标签,但实际范围和label
是不正确的.