I want to custom Slider in SwiftUI. Just something like this.
I tried Slider with GeometryReader but it isn't working.
//MARK: Left - Right Balance
GeometryReader { geo in
VStack {
Text("\(String(format: "%.2f", balanceVolume))")
HStack {
Text("L")
Slider(value: $balanceVolume, in: minValue...maxValue, step: 0.1) {editing in
print("editing", editing)
isEditing = editing
if !editing {
player.pan = Float(balanceVolume)
}
}
.tint(.none)
.accentColor(.gray)
Text("R")
}
}
.padding(20)
}
Thank you you all.
CodePudding user response:
I have created a simple custom slider, I hope it helps
Use:
struct slider: View {
@State var sliderPosition: Float = 50
var body: some View {
SliderView(value: $sliderPosition, bounds: 1...100).padding(.all)
}
}
Code:
struct SliderView: View {
let currentValue: Binding<Float>
let sliderBounds: ClosedRange<Int>
public init(value: Binding<Float>, bounds: ClosedRange<Int>) {
self.currentValue = value
self.sliderBounds = bounds
}
var body: some View {
GeometryReader { geomentry in
sliderView(sliderSize: geomentry.size)
}
}
@ViewBuilder private func sliderView(sliderSize: CGSize) -> some View {
let sliderViewYCenter = sliderSize.height / 2
let sliderViewXCenter = sliderSize.width / 2
ZStack {
RoundedRectangle(cornerRadius: 2)
.fill(Color.gray)
.frame(height: 3)
ZStack {
let sliderBoundDifference = sliderBounds.count
let stepWidthInPixel = CGFloat(sliderSize.width) / CGFloat(sliderBoundDifference)
let thumbLocation = CGFloat(currentValue.wrappedValue) * stepWidthInPixel
// Path between starting point to thumb
lineBetweenThumbs(from: .init(x: sliderViewXCenter, y: sliderViewYCenter), to: .init(x: thumbLocation, y: sliderViewYCenter))
// Thumb Handle
let thumbPoint = CGPoint(x: thumbLocation, y: sliderViewYCenter)
thumbView(position: thumbPoint, value: Float(currentValue.wrappedValue))
.highPriorityGesture(DragGesture().onChanged { dragValue in
let dragLocation = dragValue.location
let xThumbOffset = min(dragLocation.x, sliderSize.width)
let newValue = Float(sliderBounds.lowerBound / sliderBounds.upperBound) Float(xThumbOffset / stepWidthInPixel)
if newValue > Float(sliderBounds.lowerBound) && newValue < Float(sliderBounds.upperBound 1) {
currentValue.wrappedValue = newValue
}
})
}
}
}
@ViewBuilder func lineBetweenThumbs(from: CGPoint, to: CGPoint) -> some View {
Path { path in
path.move(to: from)
path.addLine(to: to)
}.stroke(Color.blue, lineWidth: 4)
}
@ViewBuilder func thumbView(position: CGPoint, value: Float) -> some View {
ZStack {
Text(String(round(value)))
.font(.headline)
.offset(y: -20)
Circle()
.frame(width: 24, height: 24)
.foregroundColor(.accentColor)
.shadow(color: Color.black.opacity(0.16), radius: 8, x: 0, y: 2)
.contentShape(Rectangle())
}
.position(x: position.x, y: position.y)
}
}