Home > Software design >  Swiftui multiple binding for a single Slider
Swiftui multiple binding for a single Slider

Time:11-11

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)
}
  • Related