Post

Replies

Boosts

Views

Activity

Reply to SwiftUI Gestures: Sequenced Long Press and Drag
This second problem – the nonexistence of a drag gesture once the long press has completed – prevents access to the location of the long-press-then-drag. Access to this location is critical for displaying to the user that the drag interaction has commenced. Problem: the LongPressGesture doesn't provide the touch location. And when you sequence the LongPressGesture before the DragGesture, the DragGesture doesn't provide the touch location until the drag actually starts. Workaround: I created a second DragGesture that's independent of the composed LongPress/DragGesture: let dragGesture2 = DragGesture(minimumDistance: 0) .onChanged { value in dragStartLocation = value.location } I then added it to my view as a simultaneousGesture: .simultaneousGesture(dragGesture2) This second DragGesture fires immediately when the view is touched so I can get the location and save it to "dragStartLocation". I then use that location to update the UI after the LongPressGesture is triggered (after minimumDuration) but before the main DragGesture runs. Downside: there will be two DragGestures. But you only use the second one to get the initial touch location so this is pretty minor. Conclusion: you can use a sequenced LongPressGesture and DragGesture as outlined in the OP's code. But if you need the initial touch location, you can add a second DragGesture in order to capture that initial location.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’25
Reply to SwiftUI Gestures: Sequenced Long Press and Drag
I started with a sequenced DragGesture and ran into the same problem: no way to get the start location (before the drag starts). Then I tried using .simultaneously instead of .sequenced: let longPressDrag = LongPressGesture(minimumDuration: 0.2) .onEnded { value in } .simultaneously(with: dragGesture) .updating($state, body: { value, state, trans in dragStartLocation = value.second?.location ?? .zero }) .onEnded({ value in dragStartLocation = .zero }) This kind of works: the LongPressGesture sets dragStartLocation (before releasing the touch or dragging). I'm using this with a ScrollView. If I quickly drag, the ScrollView scrolls. If I touch, then wait before dragging, I can set scrollDisabled on the ScrollView and the DragGesture takes over. Unfortunately, there's one big problem: the LongPressGesture always takes 1 second to process. It doesn't matter if "minimumDuration" is set to 0.1 seconds or 10 seconds. So we're left with two undesirable options: Use a sequenced gesture, which uses the correct "minimumDuration", but there's no way to get the start location. Use a simultaneous gesture, which correctly sets the start location, but doesn't respect the "minimumDuration".
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’25