SwiftUI: how to handle BOTH tap & long press of bu

2020-03-03 06:10发布

问题:

I have a button in SwiftUI and I would like to be able to have a different action for "tap button" (normal click/tap) and "long press".

Is that possible in SwiftUI?

Here is the simple code for the button I have now (handles only the "normal" tap/touch case).

Button(action: {self.BLEinfo.startScan() }) {
                        Text("Scan")
                    } .disabled(self.BLEinfo.isScanning)

I already tried to add a "longPress gesture" but it still only "executes" the "normal/short" click. This was the code I tried:

Button(action: {self.BLEinfo.startScan() }) {
                        Text("Scan")
                            .fontWeight(.regular)
                            .font(.body)
                        .gesture(
                            LongPressGesture(minimumDuration: 2)
                                .onEnded { _ in
                                    print("Pressed!")
                            }
                        )
                    }

Thanks!

Gerard

回答1:

I tried many things but finally I did something like this:

    Button(action: {
    }) {
        VStack {
            Image(self.imageName)
                .resizable()
                .onTapGesture {
                    self.action(false)
                }
                .onLongPressGesture(minimumDuration: 0.1) {
                    self.action(true)
                }
        }
    }

It is still a button with effects but short and long press are different.



回答2:

This isn't tested, but you can try to add a LongPressGesture to your button.

It'll presumably look something like this.

struct ContentView: View {
    @GestureState var isLongPressed = false

    var body: some View {
        let longPress = LongPressGesture()
            .updating($isLongPressed) { value, state, transaction in
                state = value
            }

        return Button(/*...*/)
            .gesture(longPress)
    }
}


回答3:

I just discovered that the effect depends on the order of the implementation. Implementing the detection of gestures in the following order it seems to be possible to detect and identify all three gestures:

  1. handle a double tap gesture
  2. handle a longPressGesture
  3. handle a single tap gesture

Tested on Xcode Version 11.3.1 (11C504)

    fileprivate func myView(_ height: CGFloat, _ width: CGFloat) -> some View {
    return self.textLabel(height: height, width: width)
        .frame(width: width, height: height)
        .onTapGesture(count: 2) {
            self.action(2)
        }
        .onLongPressGesture {
            self.action(3)
        }
        .onTapGesture(count: 1) {
            self.action(1)
        }
}