Search code examples
iosswiftswiftuigesture

How to implement a left or right DragGesture() that trigger a switch case in SwiftUI?


I have created a DragGesture in a View that should select a @State(Bool) whether the user swipe left or right.

The thing is that only swiping right is detected.

How to use .gesture() to capture whether a user is swiping left or right on his screen?

import SwiftUI

struct SwiftUIView: View {

  //MARK: Value to change on swipe gesture
  @State var swipeRight: Bool

  var body: some View {
    VStack {
      //MARK: Value displayed after user swiped
      Text($swipeRight ? "Right" : "Left")
    }
    .gesture(
      DragGesture()
        .onChanged { (value) in
          //MARK: What is it missing here?
          switch value.location.x {
          case ...(-0.5):
            self.swipeRight = false
            print("Swipe Left return false")
          case 0.5...:
            self.swipeRight = true
            print("Swipe Right return true")
          default: ()
          }
    })
}

Solution

  • I made a small improvement in @emehex code that will allow you to choose direction

    extension View {
        public func dismissingGesture(tolerance: Double = 24, direction: DragGesture.Value.Direction, action: @escaping () -> ()) -> some View {
            gesture(DragGesture()
                .onEnded { value in
                    let swipeDirection = value.detectDirection(tolerance)
                    if swipeDirection == direction {
                        action()
                    }
                }
            )
        }
    }
    
    extension DragGesture.Value {
        func detectDirection(_ tolerance: Double = 24) -> Direction? {
            if startLocation.x < location.x - tolerance { return .left }
            if startLocation.x > location.x + tolerance { return .right }
            if startLocation.y > location.y + tolerance { return .up }
            if startLocation.y < location.y - tolerance { return .down }
            return nil
        }
    
        enum Direction {
            case left
            case right
            case up
            case down
        }
    }
    
     .dismissingGesture(direction: .right){
                    // perform action
                }