struct ContentView: View {
@State private var sliderValue = 50.0
@State private var showSlider = true
var body: some View {
VStack {
if showSlider {
BullSlider(value: $sliderValue, in: 1.0...100.0)
}
Button("Toggle") {showSlider.toggle()}.padding()
}
}
}
struct BullSlider: View {
@Binding var value: Double
var bounds: ClosedRange<Double>
init(value: Binding<Double>, in bounds: ClosedRange<Double>) {
let thumbImage = BullThumb().snapshot()
UISlider.appearance().setThumbImage(thumbImage, for: .normal)
self.bounds = bounds
self._value = value
}
var body: some View {
Slider(value: $value, in: bounds)
}
}
struct BullThumb: View {
var body: some View {
VStack {
ZStack {
Circle()
.frame(width: 50, height: 50)
.foregroundColor(.white)
Circle()
.strokeBorder(lineWidth: 6)
.frame(width: 44, height: 44)
Circle()
.strokeBorder(lineWidth: 6)
.frame(width: 24, height: 24)
}
.foregroundColor(.blue)
Spacer()
.frame(height: 60)
}
}
}
extension View {
func snapshot() -> UIImage {
let controller = UIHostingController(rootView: self)
let view = controller.view
let targetSize = CGSize(width: 50, height: 60)//controller.view.intrinsicContentSize
view?.bounds = CGRect(origin: CGPoint(x: 0, y: 0), size: targetSize)
view?.backgroundColor = .clear
let renderer = UIGraphicsImageRenderer(size: targetSize)
return renderer.image { _ in
view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
}
}
}