Simultaneous Long Press and Drag Gesture SwiftUI

2.7k Views Asked by At

I have an app with a camera and there is a capture button that I would like to long press on the screen to record and freely move it around and be able to zoom in and out. Now I am not worried about the recording and zooming part, what I am failing to do is handle both gestures to move the button and scale the button up when it's recording.

1

There are 1 best solutions below

0
Gurjinder Singh On

iOS 16.0 I have tried what you want. Here is a sample code. There is a view that, when you long press, it will scale up, and then you can move it freely.

    enum DragState {
    case inactive
    case pressing
    case dragging(translation: CGSize)
    
    var translation: CGSize {
        switch self {
        case .inactive, .pressing:
            return .zero
        case .dragging(let translation):
            return translation
        }
    }
    
    var isDragging: Bool {
        switch self {
        case .dragging:
            return true
        case .pressing, .inactive:
            return false
        }
    }
    
    var isPressing: Bool {
        switch self {
        case .inactive:
            return false
        case .pressing, .dragging:
            return true
        }
    }
}

struct ContentView: View {
    //MARK: - PROPERTIES
    @GestureState private var dragState = DragState.inactive
    //MARK: - BODY
    var body: some View {
        VStack {
            Text("Press and Drag")
                .padding(20)
                .background(Color.blue)
                .foregroundColor(Color.white)
                .offset(x: self.dragState.translation.width, y: self.dragState.translation.height)
                .scaleEffect(dragState.isDragging ? 1.85 : 1)
                .animation(.interpolatingSpring(stiffness: 120, damping: 120), value: 1)
                .gesture(LongPressGesture(minimumDuration: 0.01)
                    .sequenced(before: DragGesture())
                    .updating(self.$dragState, body: { (value, dstate, transaction) in
                        switch value {
                        case .first:
                            dstate = .pressing
                        case .second(true, let drag):
                            dstate = .dragging(translation: drag?.translation ?? .zero)
                        default:
                            break
                        }
                    })
                )
        }
    }
}

Before Press and dragging

During Press and dragging