From 4ce04f5b191c8db3e07582f6ae7d047e0a1341a6 Mon Sep 17 00:00:00 2001 From: Anthony Golf Date: Mon, 23 Dec 2024 02:14:15 +0300 Subject: [PATCH] Implement custom thumbOffset Required to show sliders that require thumb to be center-aligned with the actual slider value (e.g. sliders with explicit notches). Default iOS slider changes its value from thumb's leftmost position to the thumb rightmost position (it is clear when you make thumb semi-transparent). --- .../HorizontalValueSliderStyle.swift | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/Sources/Sliders/ValueSlider/Styles/Horizontal/HorizontalValueSliderStyle.swift b/Sources/Sliders/ValueSlider/Styles/Horizontal/HorizontalValueSliderStyle.swift index 5eb9d61..b91d3f5 100644 --- a/Sources/Sliders/ValueSlider/Styles/Horizontal/HorizontalValueSliderStyle.swift +++ b/Sources/Sliders/ValueSlider/Styles/Horizontal/HorizontalValueSliderStyle.swift @@ -6,14 +6,15 @@ public struct HorizontalValueSliderStyle: ValueSliderS private let thumbSize: CGSize private let thumbInteractiveSize: CGSize private let options: ValueSliderOptions + private let thumbOffsets: CGFloat? public func makeBody(configuration: Self.Configuration) -> some View { let track = self.track .environment(\.trackValue, configuration.value.wrappedValue) .environment(\.valueTrackConfiguration, ValueTrackConfiguration( bounds: configuration.bounds, - leadingOffset: self.thumbSize.width / 2, - trailingOffset: self.thumbSize.width / 2) + leadingOffset: thumbOffsets ?? self.thumbSize.width / 2, + trailingOffset: thumbOffsets ?? self.thumbSize.width / 2) ) .accentColor(Color.accentColor) @@ -29,8 +30,8 @@ public struct HorizontalValueSliderStyle: ValueSliderS availableDistance: geometry.size.width, bounds: configuration.bounds, step: configuration.step, - leadingOffset: self.thumbSize.width / 2, - trailingOffset: self.thumbSize.width / 2 + leadingOffset: thumbOffsets ?? self.thumbSize.width / 2, + trailingOffset: thumbOffsets ?? self.thumbSize.width / 2 ) configuration.value.wrappedValue = computedValue } @@ -52,8 +53,8 @@ public struct HorizontalValueSliderStyle: ValueSliderS value: configuration.value.wrappedValue, availableDistance: geometry.size.width, bounds: configuration.bounds, - leadingOffset: self.thumbSize.width / 2, - trailingOffset: self.thumbSize.width / 2 + leadingOffset: thumbOffsets ?? self.thumbSize.width / 2, + trailingOffset: thumbOffsets ?? self.thumbSize.width / 2 ), y: geometry.size.height / 2 ) @@ -67,8 +68,8 @@ public struct HorizontalValueSliderStyle: ValueSliderS value: configuration.value.wrappedValue, availableDistance: geometry.size.width, bounds: configuration.bounds, - leadingOffset: self.thumbSize.width / 2, - trailingOffset: self.thumbSize.width / 2 + leadingOffset: thumbOffsets ?? self.thumbSize.width / 2, + trailingOffset: thumbOffsets ?? self.thumbSize.width / 2 ) } @@ -77,8 +78,8 @@ public struct HorizontalValueSliderStyle: ValueSliderS availableDistance: geometry.size.width, bounds: configuration.bounds, step: configuration.step, - leadingOffset: self.thumbSize.width / 2, - trailingOffset: self.thumbSize.width / 2 + leadingOffset: thumbOffsets ?? self.thumbSize.width / 2, + trailingOffset: thumbOffsets ?? self.thumbSize.width / 2 ) configuration.value.wrappedValue = computedValue @@ -94,42 +95,62 @@ public struct HorizontalValueSliderStyle: ValueSliderS .frame(minHeight: self.thumbInteractiveSize.height) } - public init(track: Track, thumb: Thumb, thumbSize: CGSize = CGSize(width: 27, height: 27), thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), options: ValueSliderOptions = .defaultOptions) { + public init(track: Track, + thumb: Thumb, + thumbSize: CGSize = CGSize(width: 27, height: 27), + thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), + options: ValueSliderOptions = .defaultOptions, + thumbOffsets: CGFloat? = nil) { self.track = track self.thumb = thumb self.thumbSize = thumbSize self.thumbInteractiveSize = thumbInteractiveSize self.options = options + self.thumbOffsets = thumbOffsets } } extension HorizontalValueSliderStyle where Track == DefaultHorizontalValueTrack { - public init(thumb: Thumb, thumbSize: CGSize = CGSize(width: 27, height: 27), thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), options: ValueSliderOptions = .defaultOptions) { + public init(thumb: Thumb, + thumbSize: CGSize = CGSize(width: 27, height: 27), + thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), + options: ValueSliderOptions = .defaultOptions, + thumbOffsets: CGFloat? = nil) { self.track = DefaultHorizontalValueTrack() self.thumb = thumb self.thumbSize = thumbSize self.thumbInteractiveSize = thumbInteractiveSize self.options = options + self.thumbOffsets = thumbOffsets } } extension HorizontalValueSliderStyle where Thumb == DefaultThumb { - public init(track: Track, thumbSize: CGSize = CGSize(width: 27, height: 27), thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), options: ValueSliderOptions = .defaultOptions) { + public init(track: Track, + thumbSize: CGSize = CGSize(width: 27, height: 27), + thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), + options: ValueSliderOptions = .defaultOptions, + thumbOffsets: CGFloat? = nil) { self.track = track self.thumb = DefaultThumb() self.thumbSize = thumbSize self.thumbInteractiveSize = thumbInteractiveSize self.options = options + self.thumbOffsets = thumbOffsets } } extension HorizontalValueSliderStyle where Thumb == DefaultThumb, Track == DefaultHorizontalValueTrack { - public init(thumbSize: CGSize = CGSize(width: 27, height: 27), thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), options: ValueSliderOptions = .defaultOptions) { + public init(thumbSize: CGSize = CGSize(width: 27, height: 27), + thumbInteractiveSize: CGSize = CGSize(width: 44, height: 44), + options: ValueSliderOptions = .defaultOptions, + thumbOffsets: CGFloat? = nil) { self.track = DefaultHorizontalValueTrack() self.thumb = DefaultThumb() self.thumbSize = thumbSize self.thumbInteractiveSize = thumbInteractiveSize self.options = options + self.thumbOffsets = thumbOffsets } }