简体   繁体   中英

DragGesture is cancelling LongPressGesture in SwiftUI

The behavior I am looking for is long press on a small image and it will get enlarged but when released it should become small again.

I was able to get this behavior successfully done; However, the problem I am having is after I press and hold I swipe my finger away from the image so I can look at it enlarged but that is being detected as a drag gesture and it cancels my behavior.

Here is my code

import SwiftUI


struct ContentView: View {
    @GestureState private var isPressingDown: Bool = false

    @State private var width: CGFloat = 64
    @State private var height: CGFloat = 64

    var body: some View {
        let longPress = LongPressGesture(minimumDuration: 0.2)
        let infiniteLongPress = LongPressGesture(minimumDuration: .infinity)
        let seq = longPress.sequenced(before: infiniteLongPress)
        let upd = seq.updating($isPressingDown) { value, state, transaction in
            switch value {
                case .second(true, nil):
                    state = true
                default:
                    break
            }
        }

        return ZStack{

            Color.black
                .opacity(self.isPressingDown ? 0.5 : 0)
                .edgesIgnoringSafeArea(.all)
                .animation(.spring())


                Image("icon")
                    .resizable()
                    .frame(width:self.isPressingDown ? self.width * 5 : self.width, height:self.isPressingDown ? self.height * 5 : self.height, alignment:.center)
                    .gesture(upd)
                    .cornerRadius(10)
                    .animation(.spring(dampingFraction: 0.65))


        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Use instead drag gesture as second one. Tested & works with Xcode 11.2

...
let longPress = LongPressGesture(minimumDuration: 0.2)
let infiniteLongPress = DragGesture(minimumDistance: 0, coordinateSpace: .local) // here !
...

sometimes Asperi's solution won't work for me so i surround the 'first gesture to receive interaction data' with highPriorityGesture, like this:

...

.highPriorityGesture(
    LongPressGesture(minimumDuration: 0.5)
        .onEnded { _ in
            // do my stuff on 0.5 sec press         
        }
)

.gesture(
    DragGesture()
        .onEnded {
            // do my stuff on drag
     }
)

...

from apple's documentation highPriorityGesture(_:including:) :

Attaches a gesture to the view with a higher precedence than gestures defined by the view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM