Como posso detectar um clique com o botão direito do mouse no SwiftUI?

10

Estou escrevendo um aplicativo simples do Mines para me ajudar a conhecer o SwiftUI. Como tal, quero que o clique primário (normalmente LMB) "cave" (revele se há um mina lá) e o clique secundário (geralmente RMB) para colocar um sinalizador.

Eu tenho a escavação trabalhando! Mas não consigo descobrir como colocar uma bandeira, porque não consigo descobrir como detectar um clique secundário.

Aqui está o que estou tentando :

BoardSquareView(
    style: self.style(for: square),
    model: square
)
.gesture(TapGesture().modifiers(.control).onEnded(self.handleUserDidAltTap(square)))
.gesture(TapGesture().onEnded(self.handleUserDidTap(square)))

Como sugeri anteriormente, a função retornada por handleUserDidTapé chamada corretamente ao clicar, mas a retornada por handleUserDidAltTapé chamada somente quando eu pressiono a tecla Control. Isso faz sentido, porque é isso que o código diz ... mas não vejo nenhuma API que possa fazer com que ele registre cliques secundários, então não sei mais o que fazer.

Eu também tentei isso, mas o comportamento parecia idêntico:

BoardSquareView(
    style: self.style(for: square),
    model: square
)
.gesture(TapGesture().modifiers(.control).onEnded(self.handleUserDidAltTap(square)))
.onTapGesture(self.handleUserDidTap(square))
Ben Leggiero
fonte
11
Seu primeiro link está quebrado. Repo privado?
Gil Birman
.onTapGesture() Confira.
Raymond
Opa, você está certo @ GilBirman! Fixo; desculpe por isso
Ben Leggiero
@ Raymond Eu tentei isso primeiro. A menos que eu esteja .gesture(TapGesture().onEnded(.......))
sentindo

Respostas:

4

Como as coisas estão no SwiftUI agora, isso não é diretamente possível. Tenho certeza de que será no futuro, mas, no momento, ele TapGestureestá claramente focado principalmente nos casos de uso do iOS que não têm o conceito de "clique direito", então acho que é por isso que isso foi ignorado. Observe que o conceito de "pressão longa" é um cidadão de primeira classe na forma de LongPressGesture, e que é usado quase exclusivamente em um contexto iOS, que suporta essa teoria.

Dito isto, eu descobri uma maneira de fazer isso funcionar. O que você precisa fazer é recorrer à tecnologia mais antiga e incorporá-la à sua visualização SwiftUI.

struct RightClickableSwiftUIView: NSViewRepresentable {
    func updateNSView(_ nsView: RightClickableView, context: NSViewRepresentableContext<RightClickableSwiftUIView>) {
        print("Update")
    }

    func makeNSView(context: Context) -> RightClickableView {
        RightClickableView()
    }

}

class RightClickableView : NSView {
    override func mouseDown(with theEvent: NSEvent) {
        print("left mouse")
    }

    override func rightMouseDown(with theEvent: NSEvent) {
        print("right mouse")
    }
}

Eu testei isso e funcionou para mim em um aplicativo SwiftUI bastante complexo. A abordagem básica aqui é:

  1. Crie seu componente de escuta como um NSView.
  2. Envolva-o com uma visualização SwiftUI implementada NSViewRepresentable.
  3. Coloque sua implementação na interface do usuário onde você desejar, como faria com qualquer outra visualização do SwiftUI.

Não é uma solução ideal, mas pode ser boa o suficiente por enquanto. Espero que isso resolva seu problema até que a Apple expanda ainda mais os recursos do SwiftUI.

BT
fonte
Obrigado. Isso é basicamente o que eu estava fazendo por enquanto . Realmente triste que esta seja sua primeira impressão com o framework. Vou marcar isso como aceito até que (espero) uma solução melhor apareça
Ben Leggiero
11
Welp; Parece que esta é a melhor resposta hoje. A recompensa é sua! Espero que um dia tenhamos uma solução oficial.
Ben Leggiero 17/01