SwiftUI: jak obsługiwać ZARÓWNO stuknięcie i długie naciśnięcie przycisku?

11

Mam przycisk w SwiftUI i chciałbym mieć możliwość wykonania innej akcji dla „przycisku stuknięcia” (normalne kliknięcie / stuknięcie) i „długiego naciśnięcia”.

Czy jest to możliwe w SwiftUI?

Oto prosty kod dla przycisku, który mam teraz (obsługuje tylko „normalną” obudowę typu dotknij / dotknij).

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

Próbowałem już dodać „gest długiego naciśnięcia”, ale nadal „wykonuje” tylko kliknięcie „normalne / krótkie”. To był kod, który próbowałem:

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

Dzięki!

Gerard

Gerard
źródło

Odpowiedzi:

15

Próbowałem wielu rzeczy, ale w końcu zrobiłem coś takiego:

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

Jest to nadal przycisk z efektami, ale krótkie i długie naciśnięcie są różne.

norkowhov
źródło
3
Należy pamiętać, że od Xcode 11.2.1 / iOS 13.2 kolejność wydaje się tutaj ważna. Używanie onLongPressGesture()przedtem onTapGesture()zignoruje ten drugi.
Koraktor
nie ma animacji stukania, naciskania i blokowania koduaction
Faruk
3

Właśnie odkryłem, że efekt zależy od kolejności wdrożenia. Wdrożenie wykrywania gestów w następującej kolejności wydaje się możliwe do wykrycia i zidentyfikowania wszystkich trzech gestów:

  1. obsłużyć gest podwójnego dotknięcia
  2. obsłużyć longPressGesture
  3. obsłużyć gest jednego dotknięcia

Testowane na Xcode w wersji 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)
        }
}
Andreas Vogel
źródło
1

To nie jest testowane, ale możesz spróbować dodać a LongPressGesturedo swojego przycisku.

Przypuszczalnie będzie to wyglądać mniej więcej tak.

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)
    }
}
Kilian
źródło
Cześć Kilian Właściwie powinienem wspomnieć, że próbowałem już dodać gest longPress, ale nadal będzie on tylko „wykonywał” akcję „normalnego kliknięcia”, a nie długie naciśnięcie. Przeredaguję mój post, aby go dodać (ponieważ jesteś drugą osobą, która to sugeruje - pierwsza usunęła swoją odpowiedź).
Gerard