Drag Gesture in SwiftUI

DevTechie Inc
Jan 6, 2023


Photo by Marek Levák on Unsplash

Drag gesture is detected when user touches the screen and moves finger to a different location.

Drag can be attached to any view by simply adding drag gesture. We mainly get three event updates about the gesture state. Drag start, drag gesture update and drag gesture end.

DragGesture takes care of providing the information about the changes with following properties:

location: this returns the current location of the finger.

translation: this property returns the distance between last location and current location

startLocation: returns initial location from where the gesture started

predictedEndLocation: returns location where dragging would stop if gesture ends immediately.

predictedEndTranslation: returns the distance between last location and location where dragging would stop if the gesture ends immediately.

Let’s look at an example for this:

struct DragGestureExample: View {
    
    @State private var cardPosition = CGPoint(x: 100, y: 100)
    @State private var cardCoordString = "100, 100"
    
    // drag gesture props
    @State private var touchLocation = CGPoint(x: 0, y: 0)
    @State private var translationValue = CGSize(width: 0, height: 0)
    @State private var startLocationValue = CGPoint(x: 0, y: 0)
    @State private var predictedEndLocationValue = CGPoint(x: 0, y: 0)
    @State private var predictedEndTranslation = CGSize(width: 0, height: 0)
    
    var body: some View {
        ZStack(alignment: .bottomTrailing) {
            VStack {
                Text("DevTechie")
                    .font(.largeTitle)
                Text("\(cardCoordString)")
            }
            .frame(width: 200, height: 100)
            .background(Color.orange, in: RoundedRectangle(cornerRadius: 10))
            .position(cardPosition)
            .gesture(DragGesture().onChanged({ newValue in
                self.cardPosition = newValue.location
                self.cardCoordString = "\(Int(newValue.location.x)), \(Int(newValue.location.y))"
                
                // drag gesture prop
                touchLocation = newValue.location
                translationValue = newValue.translation
                startLocationValue = newValue.startLocation
                predictedEndLocationValue = newValue.predictedEndLocation
                predictedEndTranslation = newValue.predictedEndTranslation
            }))
            
            VStack(alignment: .leading) {
                Text("TouchLocation: \(touchLocation.x), \(touchLocation.y)")
                Text("TranslationValue: \(translationValue.width), \(translationValue.height)")
                Text("StartLocationValue: \(startLocationValue.x), \(startLocationValue.y)")
                Text("PredictedEndLocationValye: \(predictedEndLocationValue.x), \(predictedEndLocationValue.y)")
                Text("PredictedEndTranslation: \(predictedEndTranslation.width), \(predictedEndTranslation.height)")
            }
            .font(.callout)
        }
    }
}
Gesture Location
As seen above, drag gesture provides a lots of information. Let’s use some of that information. We will start with location. We can use location value provided by drag gesture to update position of our view for example:

struct DragGestureExample: View {
    @State private var cardLocation = CGPoint(x: 0, y: 0)
    
    var body: some View {
        VStack {
            Text("DevTechie")
            Text("x: \(cardLocation.x), y: \(cardLocation.y)")
        }
        .padding()
        .background(Color.orange)
        .cornerRadius(10)
        .position(cardLocation)
        .gesture(
            DragGesture()
                .onChanged({ value in
                    cardLocation = value.location
                })
        )
    }
}
Drag Direction
We can even control the direction of drag by choosing which value to update. For example, if we only want our view to move in horizontal direction then we will only update x position for the view as shown below:

struct DragGestureExample: View {
    @State private var dragPoint = CGPoint(x: 100, y: 400)
    
    var body: some View {
        VStack {
            Text("DevTechie")
            Text("X: \(dragPoint.x), Y: \(dragPoint.y)")
        }
        .padding()
        .background(Color.orange)
        .cornerRadius(10)
        .position(x: dragPoint.x, y: dragPoint.y)
        .animation(.easeInOut, value: dragPoint)
        .gesture(
            DragGesture()
                .onChanged({ value in
                    dragPoint.x = value.location.x
                })
        )
    }
}
With that we have reached the end of this article. Thank you once again for reading. Don’t forget to follow 😍. Also subscribe our newsletter at https://www.devtechie.com