How it works
DragGesture is a gesture that recognizes a dragging motion as the user moves a finger or pointer across a view. Attach it with the gesture(_:) modifier to make a view respond to dragging — repositioning it, revealing content, or driving a custom interaction. Reach for it whenever you need continuous position data during a drag rather than a single discrete event, since it reports an updated Value throughout the motion and again when the drag finishes.
Create the gesture and attach it with gesture(_:)
DragGesture()constructs the recognizer; its initializer also acceptsminimumDistance(how far the finger must move before the drag is recognized) andcoordinateSpace(the frame the translation is measured in). You apply the gesture to a view with the.gesture(...)modifier, here attaching it to theRoundedRectangleso that view becomes draggable.Read the drag state from DragGesture.Value
As the drag proceeds,
DragGestureproduces aValuedescribing the interaction — includingstartLocation,location,predictedEndLocation, andtranslation. The example readsvalue.translation, aCGSizegiving the cumulative offset from where the drag began, which is exactly the displacement needed to move the view.Track movement with onChanged
onChanged(_:)runs your closure repeatedly while the drag is in progress, handing you the latestValueeach time. HereonChanged { value in offset = value.translation }continuously stores the translation into the@Statepropertyoffset, and because that state feeds the.offset(offset)modifier, the rectangle follows the finger in real time.Respond to completion with onEnded
onEnded(_:)fires once when the user lifts off, giving you the finalValueto settle, snap, or animate from. The example usesonEnded { _ in offset = .zero }to resetoffsetback to the origin so the rectangle springs home as soon as the drag is released.
onEnded { _ in offset = .zero } to onEnded { value in offset = value.translation } so the rectangle stays where you drop it instead of snapping back to .zero.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct DragGestureDemo: View {
@State private var offset = CGSize(width: 40, height: 20)
var body: some View {
VStack(spacing: 16) {
Text("Drag offset: \(Int(offset.width)), \(Int(offset.height))")
.font(.caption)
RoundedRectangle(cornerRadius: 12)
.fill(.blue)
.frame(width: 120, height: 120)
.offset(offset)
.gesture(
DragGesture()
.onChanged { value in offset = value.translation }
.onEnded { _ in offset = .zero }
)
}
.padding()
}
}