Responding to gestures: Dragging

Responding to gestures: Dragging

Learn how to implement drag gestures in SwiftUI to create fluid and intuitive draggable interface elements.

In SwiftUI, if you need to generate a drag gesture that invokes an action based on drag change events, use the DragGesture structure.

@State var isBeingDragged = false

var draggingGesture: some Gesture {
        DragGesture()
                .onChanged { _ in self.isBeingDragged = true }
                .onEnded { _ in self.isBeingDragged = false }
}

The onChanged(_:) and onEnded(_:) modifiers allow you to control what happens when the user performs the gesture and what happens once it stops.

When initializing a drag gesture object, you can use the DragGesture(minimumDistance:coordinateSpace:) initializer to define the smallest drag distance for the gesture to be completed, with the minimumDistance property, and in which coordinate space the gesture receives location values, with the coordinateSpace property.

struct DraggingPlaygroundView: View {
    
    let circleSize: CGFloat = 75
    
    @State var isDragging = false
    @State var currentPosition: CGPoint = .zero
    
    var draggingObject: some Gesture {
        DragGesture(minimumDistance: 1, coordinateSpace: .local)
            .onChanged { gesture in
                self.isDragging = true
                self.currentPosition = gesture.location
            }
            .onEnded { _ in self.isDragging = false }
    }
    
    
    var body: some View {
        Circle()
            .fill(Color.blue)
            .shadow(color: .primary, radius: isDragging ? 3 : 0, x: 0, y: isDragging ? 5 : 0)
            .frame(width: circleSize, height: circleSize, alignment: .center)
            .position(currentPosition)
            .gesture(draggingObject)
            .onAppear {
                setupView()
            }
    }
    
    private func setupView() {
        let initialX = UIScreen.main.bounds.width / 2
        let initialY = UIScreen.main.bounds.height / 2
        
        currentPosition = CGPoint(x: initialX, y: initialY)
    }
}
0:00
/0:10