Home > front end >  SwiftUI Slider Value Not Respecting the Range
SwiftUI Slider Value Not Respecting the Range

Time:10-04

I have a tab view with two tabs, with the second tab having a slider that ranges from 0 to a maximum value (computed property) that depends on the current width of the device (based on the orientation). However, when the orientation is changed, the range seems to be updated correctly but not the value, this is evident since when the orientation changes and the maximum value is updated, if I click on the slider on its maximum position, the value is updated accordingly.

Below is a sample code that represents my issue. import SwiftUI

enum Tab: String {
    case Tab1, Tab2
}

struct TabView1: View {
    var body: some View {
        NavigationView {
            GeometryReader { proxy in
                Text("Tab View 1")
                
                .navigationBarTitle("Tab View 1")
            }
        }
    }
}

struct TabView2: View {
    @State var sliderValue: Double = 1.0
    var width: CGFloat
    
    var maxSliderValue: Double {
        (Double(width) * 0.1 / 6.0).rounded()
    }
    
    var body: some View {
        NavigationView {
            VStack {
                Slider(value: $sliderValue, in: 0...maxSliderValue, step: 1) {
                    Label("Slider", systemImage: "circle")
                }
                Text("Value: \(String(format: "%.f", sliderValue))")
            }
            
            .navigationBarTitle("Tab View 2")
        }
    }
}

struct ContentView: View {
    @State var currentTab: Tab = .Tab2
    
    var body: some View {
        GeometryReader { proxy in
            TabView(selection: $currentTab) {
                TabView1()
                    .tag(Tab.Tab1)
                    .tabItem {
                        Label(Tab.Tab1.rawValue, systemImage: "square")
                    }
                
                TabView2(width: proxy.size.width)
                    .tag(Tab.Tab2)
                    .tabItem {
                        Label(Tab.Tab2.rawValue, systemImage: "triangle")
                    }
            }
        }
    }
}

For example, in portrait mode, where the width is 375, the maximum value for the slider is 6. And in landscape mode the width is 724, the maximum value for the slider is 12.

In portrait mode, the slider is shown below. Portrait mode

Change to landscape mode and change the slider to the maximum value. Lanndscape mode

Change back to portrait mode, the slider's position is at the maximum but the value is still at 12. Portrait after landscape

When I click on the slider, the value displayed then changes to 6. Is how I'm sending the width of the screen wrong and causing this issue, or is there a way to force the slider value to update based on the maximum value and fix itself?

I also wanted to check the width property in TabView2 struct if it was changing, so I added willSet and didSet to check the values, however, none of the print statements inside it were printed to the console.

CodePudding user response:

When maxSliderValue value changed slider value also not changed and that's why the label is still showing the old value. You can update the value by observing the change in maxSliderValue and update the value.

Slider(value: $sliderValue, in: 0...maxSliderValue, step: 1) {
    Label("Slider", systemImage: "circle")
}.onChange(of: maxSliderValue, perform: { value in
    sliderValue = min(value, sliderValue)
})

  • Related