SwiftUI: como lidar com os dois toques e pressão prolongada do botão?

11

Eu tenho um botão no SwiftUI e gostaria de poder executar uma ação diferente para "toque no botão" (clique / toque normal) e "pressione e segure".

Isso é possível no SwiftUI?

Aqui está o código simples para o botão que tenho agora (lida apenas com a caixa de toque / toque "normal").

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

Eu já tentei adicionar um "gesto longPress", mas ele ainda apenas "executa" o clique "normal / curto". Este foi o código que tentei:

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

Obrigado!

Gerard

Gerard
fonte

Respostas:

15

Eu tentei muitas coisas, mas finalmente fiz algo assim:

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

Ainda é um botão com efeitos, mas a pressão curta e longa são diferentes.

norekhov
fonte
3
Observe que, a partir do Xcode 11.2.1 / iOS 13.2, o pedido parece ser importante aqui. Usar onLongPressGesture()antes onTapGesture()ignorará o último.
Koraktor #
isso não tem a animação de tocar ou pressionar e bloquear o códigoaction
Faruk
3

Acabei de descobrir que o efeito depende da ordem da implementação. Implementando a detecção de gestos na seguinte ordem, parece possível detectar e identificar os três gestos:

  1. lidar com um gesto de toque duplo
  2. lidar com um longPressGesture
  3. lidar com um único gesto de toque

Testado no Xcode versão 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
fonte
1

Isso não foi testado, mas você pode tentar adicionar um LongPressGestureao seu botão.

Presumivelmente, será algo parecido com isto.

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
fonte
Oi Kilian Na verdade, eu deveria ter mencionado que já havia tentado adicionar um gesto longPress, mas ainda assim "executaria" a ação "clique normal" e não a pressão longa. Vou editar meu post para adicionar isso (como você é a segunda pessoa a sugerir isso - a primeira excluiu sua resposta).
Gerard