Jak mogę wykryć kliknięcie prawym przyciskiem myszy w SwiftUI?

10

Piszę prostą aplikację Mines, która pomoże mi poznać SwiftUI. W związku z tym chcę, aby główne kliknięcie (zwykle LMB) „wykopało” (ujawnij, czy jest tam kopalnia), a drugie kliknięcie (zwykle RMB), aby umieścić flagę.

Kopanie działa! Ale nie mogę wymyślić, jak umieścić flagę, ponieważ nie mogę wymyślić, jak wykryć drugie kliknięcie.

Oto, co próbuję :

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

Jak sugerowałem wcześniej, funkcja zwracana przez handleUserDidTapjest wywoływana poprawnie po kliknięciu, ale funkcja zwracana przez handleUserDidAltTapjest wywoływana tylko wtedy, gdy przytrzymuję klawisz Control. Ma to sens, ponieważ tak mówi kod ... ale nie widzę żadnego interfejsu API, który mógłby zmusić go do zarejestrowania dodatkowych kliknięć, więc nie wiem, co jeszcze zrobić.

Próbowałem również tego, ale zachowanie wydawało się identyczne:

BoardSquareView(
    style: self.style(for: square),
    model: square
)
.gesture(TapGesture().modifiers(.control).onEnded(self.handleUserDidAltTap(square)))
.onTapGesture(self.handleUserDidTap(square))
Ben Leggiero
źródło
1
Twój pierwszy link jest uszkodzony. Prywatne repozytorium?
Gil Birman,
.onTapGesture() Sprawdź to.
Raymond,
Ups, masz rację @GilBirman! Naprawiony; przepraszam za to
Ben Leggiero,
@ Raymond Próbowałem tego pierwszy. Chyba że brakuje mi czegoś dużego, wydaje się, że zachowuje się identycznie.gesture(TapGesture().onEnded(.......))
Ben Leggiero,

Odpowiedzi:

4

W obecnej sytuacji ze SwiftUI nie jest to bezpośrednio możliwe. Jestem pewien, że tak będzie w przyszłości, ale w tej chwili TapGesturewyraźnie koncentruje się głównie na przypadkach użycia iOS, które nie mają koncepcji „kliknięcia prawym przyciskiem”, więc myślę, że dlatego to zostało zignorowane. Zwróć uwagę, że koncepcja „długiego naciśnięcia” jest obywatelem pierwszej klasy w postaci LongPressGesture, i jest prawie wyłącznie używana w kontekście iOS, który obsługuje tę teorię.

To powiedziawszy, wymyśliłem sposób, aby to zadziałało. Musisz polegać na starszej technologii i osadzić ją w widoku 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")
    }
}

Przetestowałem to i działało dla mnie w dość złożonej aplikacji SwiftUI. Podstawowe podejście tutaj:

  1. Utwórz swój komponent odsłuchowy jako NSView.
  2. Zawiń to za pomocą widoku SwiftUI, który implementuje NSViewRepresentable.
  3. Umieść swoją implementację w interfejsie użytkownika w dowolnym miejscu, tak jak w przypadku każdego innego widoku SwiftUI.

Nie jest to idealne rozwiązanie, ale na razie może być wystarczające. Mam nadzieję, że to rozwiąże Twój problem, dopóki Apple nie rozszerzy możliwości SwiftUI.

BT
źródło
Dziękuję Ci. Zasadniczo to właśnie robiłem . Naprawdę smutne, że to ich pierwsze wrażenie z frameworkiem. Oznaczę to jako zaakceptowane, dopóki (mam nadzieję 🤞🏼) nie pojawi się lepsze rozwiązanie
Ben Leggiero
1
Welp; wygląda na to, że jest to najlepsza odpowiedź dzisiaj. Nagroda jest twoja! Mamy nadzieję, że kiedyś będziemy mieli oficjalne rozwiązanie.
Ben Leggiero