How can I bind multiple variables to a single Slider is SwiftUI?
I would like to have 1 slider that changes 2 variables, one in a range from 1 to 5 and another from 1000 to 1200. Or any workaround for this?
So when variable1 = 1, variable2 should be 1000 and when variable1 = 5, variable2 should be 1200 and everything in between. Thanks (I'm new to programming)
struct ContentView: View {
@State private var variable1 = 1.0
@State private var variable2 = 1000.0
var body: some View {
VStack {
Slider(value: $variable1, in: 1...5, step: 0.25)
}
}
}
CodePudding user response:
One solution is, instead of using a second @State
variable, to use a computed property:
struct ContentView: View {
@State private var variable1 = 1.0
private var variable1Range = 1.0...5.0
private var variable2Range = 1000.0...1200.0
var variable2 : Double {
floatingMap(minRange: variable1Range.lowerBound, maxRange: variable1Range.upperBound, minDomain: variable2Range.lowerBound, maxDomain: variable2Range.upperBound, value: variable1)
}
var body: some View {
VStack {
Text("Variable 1: \(variable1)")
Text("Variable 2: \(variable2)")
Slider(value: $variable1, in: variable1Range, step: 0.25)
}
}
}
func floatingMap<T:FloatingPoint>(minRange:T, maxRange:T, minDomain:T, maxDomain:T, value:T) -> T {
return minDomain (maxDomain - minDomain) * (value - minRange) / (maxRange - minRange)
}
If you truly need two @State
variables, you could use onChange
to watch variable1
and assign a new value on variable2
based on its value:
struct ContentView: View {
@State private var variable1 = 1.0
@State private var variable2 = 1000.0
private var variable1Range = 1.0...5.0
private var variable2Range = 1000.0...1200.0
var body: some View {
VStack {
Text("Variable 1: \(variable1)")
Text("Variable 2: \(variable2)")
Slider(value: $variable1, in: variable1Range, step: 0.25)
}.onChange(of: variable1) { variable1 in
variable2 = floatingMap(minRange: variable1Range.lowerBound, maxRange: variable1Range.upperBound, minDomain: variable2Range.lowerBound, maxDomain: variable2Range.upperBound, value: variable1)
}
}
}
func floatingMap<T:FloatingPoint>(minRange:T, maxRange:T, minDomain:T, maxDomain:T, value:T) -> T {
return minDomain (maxDomain - minDomain) * (value - minRange) / (maxRange - minRange)
}