I am trying to make a slider update a value if it changes. In this case, I'm looking for a lower and upper bound in a range from 0 to 4. If the min value is greater than the max value, I want the max to update (to equal the min value). I want the same to happen in reverse - if the max is slid to less than the min, the min should automatically update to compensate.
import SwiftUI
struct ContentView: View {
@State private var numPeople: [Double] = [0, 2]
var body: some View {
VStack {
Text("Hello, world!")
Section(header: Text("Number of People")) {
createEditableRangeSection(values: $numPeople, range: 0...4)
}
}
.padding()
}
func createEditableRangeSection(values: Binding<[Double]>, range: ClosedRange<Double>) -> some View {
VStack {
HStack {
Text("Min: \((values.wrappedValue[0]))")
Slider(value: values[0], in: range, step: 1)
.onChange(of: values.wrappedValue[0]) { newValue, _ in
if Int(newValue) >= 3 {
print (newValue, values.wrappedValue[1])
}
if newValue > values.wrappedValue[1] {
values.wrappedValue[1] = newValue
}
}
}
HStack {
Text("Max: \((values.wrappedValue[1]))")
Slider(value: values[1], in: range, step: 1)
.onChange(of: values.wrappedValue[1]) { newValue, _ in
if newValue < values.wrappedValue[0] {
values.wrappedValue[0] = newValue
}
}
}
}
}
}
This code works perfectly with a large range (like 20...200) but for the range of 0...4 it has an interesting effect. You can move the min to the value of (max + 1) and release it, and it looks like this:
However, if you grab it and slowly move it back to the previous position (max) the max value will suddenly update and jump to the right.
The first parameter of the onChange
closure is the old value, not the new value!
You should change
.onChange(of: ...) { newValue, _ in ... }
to
.onChange(of: ...) { _, newValue in ... }