TechnologiesSwiftUI

DragGesture struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A dragging motion that invokes an action as the drag-event sequence changes.

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.

  1. Create the gesture and attach it with gesture(_:)

    DragGesture() constructs the recognizer; its initializer also accepts minimumDistance (how far the finger must move before the drag is recognized) and coordinateSpace (the frame the translation is measured in). You apply the gesture to a view with the .gesture(...) modifier, here attaching it to the RoundedRectangle so that view becomes draggable.

  2. Read the drag state from DragGesture.Value

    As the drag proceeds, DragGesture produces a Value describing the interaction — including startLocation, location, predictedEndLocation, and translation. The example reads value.translation, a CGSize giving the cumulative offset from where the drag began, which is exactly the displacement needed to move the view.

  3. Track movement with onChanged

    onChanged(_:) runs your closure repeatedly while the drag is in progress, handing you the latest Value each time. Here onChanged { value in offset = value.translation } continuously stores the translation into the @State property offset, and because that state feeds the .offset(offset) modifier, the rectangle follows the finger in real time.

  4. Respond to completion with onEnded

    onEnded(_:) fires once when the user lifts off, giving you the final Value to settle, snap, or animate from. The example uses onEnded { _ in offset = .zero } to reset offset back to the origin so the rectangle springs home as soon as the drag is released.

Try it — Change 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.

DragGesture.swift
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()
    }
}
Live preview
Drag offset: 40, 20
Drag offset: 40, 20
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →