Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a bunch of vertical sliders in swiftUI

I am trying to make a group (10 in the test code, but 32 in reality) of vertical faders using SwiftUI on an iPad app. When making sliders horizontally, they stretch across the screen properly. When rotating those same sliders vertical, they seem locked into their horizontal dimensions. Is there a simple way to get the sliders to be vertical?

Horizontal (stretches across screen):

import SwiftUI

struct ContentView: View {
    @State private var sliderVal: Double = 0
    @State var values: [Double] = Array.init(repeating: 0.0, count: 10)

    var body: some View {
        VStack() {
            ForEach((0 ... 9), id: \.self) {i in
                HStack {
                    Text("\(i): ")
                    Slider(value: self.$values[i], in: 0 ... 100, step: 1.0)
                        .colorScheme(.dark)
                    Text("\(Int(self.values[i]))")
                }
            }
        }
    }
}

Switching the stack views and rotating the sliders (does not work):

struct ContentView: View {
    @State private var sliderVal: Double = 0
    @State var values: [Double] = Array.init(repeating: 0.0, count: 10)

    var body: some View {
        HStack() {
            ForEach((0 ... 9), id: \.self) {i in
                VStack {
                    Text("\(i): ")
                    Slider(value: self.$values[i], in: 0 ... 100, step: 1.0)
                        .colorScheme(.dark)
                        .rotationEffect(.degrees(-90))
                    Text("\(Int(self.values[i]))")
                }
            }
        }
    }
}
like image 268
fishymander Avatar asked Sep 24 '19 04:09

fishymander


Video Answer


2 Answers

You can make vertical sliders from horizontal ones in SwiftUI, the trick is frame(width:) and frame(height:) are swapped. Here is what I did to make some really nice vertical sliders using the built-in SwiftUI functions

import SwiftUI

struct VerticalSlider: View {
    @EnvironmentObject var playData : PlayData
    var channelNumber:Int
    var sliderHeight:CGFloat

    var body: some View {
        Slider(
            value: self.$playData.flickerDimmerValues[self.channelNumber],
            in: 0...255,
            step: 5.0
        ).rotationEffect(.degrees(-90.0), anchor: .topLeading)
        .frame(width: sliderHeight)
        .offset(y: sliderHeight)
    }
}

Then pass the Slider frame(width: ) to the above code in the variable sliderHeight as in the following code, where sliderHeight is the layout dimension provided by SwiftUI when it is laying out the view. This is a slick use of GeometryReader to size the slider exactly right.

import SwiftUI

struct VerticalBar: View {
    @EnvironmentObject var playData : PlayData
    var channelNumber:Int

    var body: some View {
        VStack {
            GeometryReader { geo in
                VerticalSlider(
                    channelNumber: self.channelNumber,
                    sliderHeight: geo.size.height
                )
            }
            Text("\(self.channelNumber + 1)")
                .font(.headline)
                .frame(height: 10.0)
                .padding(.bottom)
           
        }
    }
}

I then put 8 of the above views within a view area using a HStack:

HStack {
    Spacer(minLength: 5.0)
    VerticalBar(channelNumber: 0)
    VerticalBar(channelNumber: 1)
    VerticalBar(channelNumber: 2)
    VerticalBar(channelNumber: 3)
    VerticalBar(channelNumber: 4)
    VerticalBar(channelNumber: 5)
    VerticalBar(channelNumber: 6)
    VerticalBar(channelNumber: 7)
    Spacer(minLength: 5.0)
}

When completed, the vertical sliders look like this:

enter image description here

like image 181
grapeffx Avatar answered Oct 22 '22 01:10

grapeffx


I made a custom VSlider view (source on GitHub) to address this issue. It should be virtually identical in usage to a Slider, as shown in the comparison demo below (although it's not generic, so it has to be used with a Double).

VSlider demo

like image 34
John M. Avatar answered Oct 22 '22 01:10

John M.