Comment puis-je détecter un clic droit dans SwiftUI?


10

J'écris une application simple Mines me aider à mieux connaître SwiftUI. En tant que tel, je veux que le clic principal (généralement LMB) "creuse" (révèle s'il y a une mine là-bas), et un clic secondaire (généralement RMB) pour placer un drapeau.

J'ai le travail de creusage! Mais je ne peux pas comprendre comment placer un indicateur, car je ne peux pas comprendre comment détecter un clic secondaire.

Voici ce que j'essaie :

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

Comme je l'ai laissé entendre précédemment, la fonction renvoyée par handleUserDidTapest appelée correctement lors d'un clic, mais celle renvoyée par handleUserDidAltTapn'est appelée que lorsque je maintiens la touche Ctrl enfoncée. C'est logique parce que c'est ce que dit le code ... mais je ne vois aucune API qui pourrait lui permettre d'enregistrer des clics secondaires, donc je ne sais pas quoi faire d'autre.

J'ai également essayé cela, mais le comportement semblait identique:

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

1
Votre premier lien est rompu. Repo privé?
Gil Birman

.onTapGesture() Vérifiez-le.
Raymond

Oups, vous avez raison @GilBirman! Fixé; désolé
Ben Leggiero

@Raymond J'ai essayé ça en premier. À moins que je manque quelque chose de gros, il semble se comporter de la même manière.gesture(TapGesture().onEnded(.......))
Ben Leggiero

Réponses:


4

En l'état actuel des choses avec SwiftUI, ce n'est pas directement possible. Je suis sûr que ce sera dans le futur, mais pour le moment, il TapGestureest clairement axé principalement sur les cas d'utilisation iOS qui n'ont pas un concept de "clic droit", donc je pense que c'est pourquoi cela a été ignoré. Remarquez que le concept de «presse longue» est un citoyen de première classe sous la forme de LongPressGesture, et qui est presque exclusivement utilisé dans un contexte iOS, qui soutient cette théorie.

Cela dit, j'ai trouvé un moyen de faire fonctionner cela. Ce que vous devez faire, c'est vous replier sur l'ancienne technologie et l'intégrer dans votre vue 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")
    }
}

J'ai testé cela, et cela a fonctionné pour moi dans une application SwiftUI assez complexe. L'approche de base ici est:

  1. Créez votre composant d'écoute en tant que NSView.
  2. Enveloppez-le avec une vue SwiftUI qui implémente NSViewRepresentable.
  3. Plop votre implémentation dans l'interface utilisateur où vous le souhaitez, tout comme vous le feriez avec n'importe quelle autre vue SwiftUI.

Ce n'est pas une solution idéale, mais cela pourrait être suffisant pour le moment. J'espère que cela résout votre problème jusqu'à ce qu'Apple élargisse les capacités de SwiftUI.


Je vous remercie. C'est essentiellement ce que je faisais pour l'instant . Vraiment triste que ce soit leur première impression avec le cadre. Je marquerai ceci comme accepté jusqu'à ce que (espérons-le 🤞🏼) une meilleure solution se présente
Ben Leggiero

1
Welp; ressemble à ceci est la meilleure réponse aujourd'hui. La prime vous appartient! J'espère qu'un jour nous aurons une solution officielle.
Ben Leggiero
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.