๐๏ธSliderWithLabel
Last updated
Last updated
swiftโฉ custom โฉ control โฉ SliderWithLabel
ๅฏ่ช่จๆจ้ก่ๆธๅผๆ ผๅผ็ Sliderใ
// (defaults) in: 0...1, step: nil, specifier: "%.2f"
SliderWithLabel(
value: $t
) { Text("ๅฏฌๅบฆ(0-1)๏ผ") } // title label
SliderWithLabel(
value: $m, in: 100...200, step: 1, // step = 1
specifier: "%.0f" // integer
) { Text("้ณ้(0-200)๏ผ") } // title label
SliderWithLabel(
value: $n, in: 0...100, step: 5, // step = 5
specifier: "%.0f" // integer
) { Text("้ณ้(0,5...100)๏ผ") }
import SwiftUI
import GeometryKit
struct SliderWithLabel<
V: BinaryFloatingPoint & _FormatSpecifiable,
TitleLabel: View
// ValueLabel: View
>: View where V.Stride: BinaryFloatingPoint {
@Binding var value: V
let `in`: ClosedRange<V>
let step: V.Stride?
var min: V { `in`.lowerBound }
var max: V { `in`.upperBound }
var t: V { (value - min)/(max - min) }
let specifier: String // like "%.0f"
/*@ViewBuilder*/ let titleLabel: () -> TitleLabel
let knobWidth: CGFloat = 28
let yOffset: CGFloat = -16
init(value: Binding<V>, in bounds: ClosedRange<V>, step: V.Stride? = nil, specifier: String = "%.0f", titleLable: @escaping () -> TitleLabel = {Text("Untitled")}){
self._value = value
self.in = bounds
self.step = step
self.specifier = specifier
self.titleLabel = titleLable
}
var body: some View {
HStack {
titleLabel()
sliderWithValueLabel
}
.padding(.top, 30)
}// body
// slider
@ViewBuilder var slider: some View {
if let step = step {
Slider(value: $value, in: `in`, step: step)
} else {
Slider(value: $value, in: `in`)
}
}
// slider + value label
var sliderWithValueLabel: some View {
slider
.background {
GeometryReader { geo in
Text("\(value, specifier: specifier)")
// โญ๏ธ position label directly
.position(geo.size[CGFloat(t), 0]) // GeometryKit
.offset(y: yOffset) // move upward
}//GeometryReader
.padding(.horizontal, knobWidth/2) // โญ๏ธ knob half width
}// slider.background
}// sliderWithValueLabel
}// ValueSlider
๐ Examples & Previews
// value slider example
private struct SliderWithLabelExample: View {
@State var m: CGFloat = 150 // 100, 101 ... 200 (integer)
@State var t: CGFloat = 0.8 // 0 ... 1 (decimal)
@State var n: CGFloat = 25 // 0, 5, ... 100 (integer)
var body: some View {
VStack {
Spacer()
Form {
SliderWithLabel( // in : 0...1 (default)
value: $t // step : nil (default)
) { Text("ๅฏฌๅบฆ(0-1)๏ผ") } // specifier: "%.2f" (default)
SliderWithLabel(
value: $m, in: 100...200, step: 1, // step = 1
specifier: "%.0f" // integer
) { Text("้ณ้(0-200)๏ผ") }
.frame(maxWidth: 500)
SliderWithLabel(
value: $n, in: 0...100, step: 5, // step = 5
specifier: "%.0f" // integer
) { Text("้ณ้(0,5...100)๏ผ") }
.accentColor(.red)
}// Form
Spacer()
}
}// body
}// ValueSliderExample
// ------------- Previews --------------
// previews
struct SliderWithLabel_Previews: PreviewProvider {
static var previews: some View {
SliderWithLabelExample()
}
}
GeometryKit๏ผๅฉ็จ size[x, y]
็่ชๆณไพ่จ็ฎไฝ็ฝฎใ
SliderWithLabel
๏ผ
ไฝฟ็จ ๏ผ Binding ่ฎๆธใ
Slider label position๏ผ่ฌ่งฃๅฆไฝๆบๆพๆธๅผๆจ็ฑค็็ดฐ็ฏใ