@@ -35,7 +35,7 @@ import SwiftUI
3535/// ```
3636///
3737/// Additionally, the `onEditingChanged` closure allows you to perform various animations or change the state.
38- ///
38+ ///
3939/// ```swift
4040/// @State private var progress = 0.5
4141/// @State private var isEditing = false
@@ -68,6 +68,8 @@ public struct SeekBar: View {
6868 private let onEditingChanged : ( Bool ) -> Void
6969
7070 @State private var dragStartOffset : CGFloat = 0
71+ // Threshold to distinguish between taps and drags
72+ private let tapThreshold : CGFloat = 3
7173
7274 public var body : some View {
7375 GeometryReader { proxy in
@@ -78,23 +80,53 @@ public struct SeekBar: View {
7880 Track ( value: value, bufferedValue: bufferedValue, bounds: bounds)
7981 . frame ( height: trackDimensions. trackHeight)
8082 . allowsHitTesting ( allowsTrackHitTesting)
81- . gesture ( dragGesture ( availableWidth: availableWidth) )
83+ . gesture ( trackGesture ( availableWidth: availableWidth) )
8284
8385 Handle ( )
8486 . frame ( width: handleSize, height: handleSize)
8587 . opacity ( isDisplayOnlyTrack ? 0 : 1 )
8688 . offset ( x: calculatePosition ( for: value, within: bounds, with: availableWidth) )
8789 . allowsHitTesting ( allowsHandleHitTesting)
88- . gesture ( dragGesture ( availableWidth: availableWidth) )
90+ . gesture ( handleGesture ( availableWidth: availableWidth) )
8991 }
9092 }
9193 . frame ( height: seekBarMaxHeight)
9294 }
9395
94- /// Creates a `DragGesture` to handle dragging interactions.
95- ///
96- /// - Parameter availableWidth: The available width for calculating drag positions.
97- private func dragGesture( availableWidth: CGFloat ) -> some Gesture {
96+ /// Creates a gesture for the track that handles both taps and drags
97+ private func trackGesture( availableWidth: CGFloat ) -> some Gesture {
98+ // Use a simultaneous gesture to handle both taps and drags
99+ SimultaneousGesture (
100+ TapGesture ( )
101+ . onEnded { _ in
102+ // Tap handling not needed here as we'll handle it in the drag gesture
103+ } ,
104+ DragGesture ( minimumDistance: 0 )
105+ . onChanged { dragValue in
106+ let distance = abs ( dragValue. startLocation. x - dragValue. location. x)
107+
108+ if distance <= tapThreshold {
109+ // Treat as tap - immediate seek
110+ onEditingChanged ( true )
111+ value = normalizedValue ( for: dragValue. location. x, within: bounds, with: availableWidth, step: step)
112+ } else {
113+ // Treat as drag
114+ onEditingChanged ( true )
115+ if isActionMoveWithValue {
116+ value = normalizedValue ( for: dragValue. location. x, within: bounds, with: availableWidth, step: step)
117+ }
118+ updateValueWithDrag ( dragValue: dragValue, availableWidth: availableWidth)
119+ }
120+ }
121+ . onEnded { _ in
122+ dragStartOffset = 0
123+ onEditingChanged ( false )
124+ }
125+ )
126+ }
127+
128+ /// Creates a gesture specifically for the handle (drag only)
129+ private func handleGesture( availableWidth: CGFloat ) -> some Gesture {
98130 DragGesture ( minimumDistance: 0 )
99131 . onChanged { dragValue in
100132 onEditingChanged ( true )
0 commit comments