Sobes.tech
Middle

Wie erkennt man, ob der Benutzer auf eine Ebene (Layer) in der Anwendung geklickt hat?

sobes.tech KI

Antwort von AI

Verwenden Sie die Methode hitTest: auf UIView, in die diese Schicht eingebettet ist, oder überprüfen Sie, ob der Berührungspunkt zum Rahmen der Schicht gehört, indem Sie containsPoint: oder hitTest: verwenden.

Beispiel für die Erkennung einer Berührung auf der Schicht innerhalb von touchesBegan:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let locationInView = touch.location(in: self.view)
    let locationInLayer = self.view.layer.convert(locationInView, to: myLayer) // Punkt in die Koordinaten der Schicht umwandeln

    if myLayer.contains(locationInLayer) {
        // Der Benutzer hat myLayer berührt
        print("Schicht berührt!")
    }
}

sobes.tech KI

Antwort von AI

Sie können den Hit-Test verwenden: Bestimmen, auf welcher Ebene die Berührung genau stattgefunden hat. Core Animation bietet dafür zwei Methoden:

  1. hitTest(_:):

    • Prüft, ob der Punkt innerhalb der Grenzen der Ebene oder einer ihrer Unterebenen liegt.
    • Gibt die tiefste Unterebene (oder die Ebene selbst) zurück, die den Punkt enthält.
    • Berücksichtigt isHidden = true.
  2. contains(_:):

    • Prüft nur, ob der Punkt innerhalb der Grenzen der Ebene liegt.
    • Berücksichtigt die Hierarchie der Unterebenen nicht.
    • Berücksichtigt isHidden nicht.

Normalerweise wird hitTest verwendet, da es genauer ist, um die Interaktivität zu bestimmen.

Beispiel für die Verwendung von hitTest in einem Touch-Handler:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }

    let locationInView = touch.location(in: view)

    // Konvertieren Sie den Punkt von den Koordinaten der Ansicht in die Koordinaten der Ebene
    let locationInLayer = myLayer.convert(locationInView, from: view.layer)

    // Führen Sie den Hit-Test durch
    if let hitLayer = myLayer.hitTest(locationInLayer) {
        if hitLayer === myLayer {
            // Genau myLayer berührt
            print("myLayer wurde berührt")
        } else {
            // Unterebene innerhalb von myLayer berührt
            print("Unterebene innerhalb von myLayer wurde berührt")
            // Die Identifikation der Unterebene kann zusätzliche Überprüfungen erfordern
        }
    } else {
        // Außerhalb von myLayer und seinen Unterebenen berührt
        print("Außerhalb von myLayer berührt")
    }
}

Wichtige Punkte:

  • Die Koordinaten des Berührungspunkts (location(in:)) sind immer an UIView gebunden. Sie müssen in das Koordinatensystem der Ebene (convert(_, from:) oder convert(_, to:)) umgewandelt werden.
  • Die Methode hitTest(_:) arbeitet mit Punkten im Koordinatensystem der aufrufenden Ebene (myLayer.hitTest(locationInLayer)).
  • Wenn die Ebene unsichtbar ist (alpha = 0 oder isHidden = true), gibt hitTest nil zurück. contains gibt true zurück, wenn der Punkt innerhalb der Grenzen liegt, unabhängig von der Sichtbarkeit.
  • Für komplexe Hierarchien von Ebenen kann eine rekursive Suche oder die Überprüfung der zurückgegebenen hitLayer erforderlich sein.

sobes.tech KI

Antwort von AI

Um CALayer-Touch kann auf verschiedene Weisen erkannt werden:

  1. Verwendung von hitTest(_:event:) im View:

    • UIView hat die Methode hitTest(_:with:), die rekursiv durch die Hierarchie der Subviews geht und die tiefste Ansicht zurückgibt, die den Punkt enthält.
    • Diese Methode berücksichtigt standardmäßig die mit den Views verbundenen Layer.
    • Man kann hitTest(_:with:) in einer benutzerdefinierten Ansicht überschreiben, um eine detailliertere Kontrolle zu haben oder um Touches direkt auf Sub-Layern zu behandeln, die nicht mit Views verbunden sind.
  2. Koordinaten mit convert transformieren:

    • Beim Empfang eines Touch-Events (z.B. in UIView-Methoden) hat man die Koordinaten des Touches relativ zum Fenster (UIWindow) oder zur Ansicht.
    • Um zu bestimmen, ob der Touch auf einen bestimmten Layer gefallen ist, muss man diese Koordinaten in das Koordinatensystem dieses Layers umrechnen.
    • Dafür werden die Methoden convert(_:from:) oder convert(_:to:) von CALayer verwendet.
    • Nach der Umrechnung kann man prüfen, ob der Punkt innerhalb der Grenzen des Layers (bounds) liegt oder spezifischere Prüfungen wie contains(_:) verwenden.
  3. UITapGestureRecognizer an die Ansicht anhängen:

    • Man kann einen UITapGestureRecognizer an die UIView anhängen, die mit dem Layer verbunden ist.
    • Im Gesten-Handler erhält man die Position des Touches relativ zur Ansicht.
    • Dann kann man die Koordinatenumwandung (Punkt 2) verwenden, um zu prüfen, ob der Touch innerhalb des Layers oder seiner Sub-Layers liegt.
  4. Erstellen einer UIView für jeden interaktiven Layer:

    • Wenn Sie Layer haben, die interaktiv sein sollen, ist eine einfache Methode, für jeden Layer eine UIView zu erstellen.
    • Positionieren und anpassen Sie die Größe der UIView, um mit dem Layer übereinzustimmen.
    • Fügen Sie Gesten-Handler (UITapGestureRecognizer) hinzu oder überschreiben Sie Methoden zur Touch-Verarbeitung (touchesBegan, touchesEnded etc.) in dieser Ansicht.
    • Dies ist die idiomatischste Methode, um Benutzereingaben in UIKit zu verarbeiten, da UIView dafür speziell gemacht ist.

Beispiel für die Verwendung von hitTest in UIView:

// In einer benutzerdefinierten UIView
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    // Punkt in die Koordinaten der Sublayer umrechnen
    let pointInLayer = mySublayer.convert(point, from: layer!)
    
    // Prüfen, ob der Punkt innerhalb der Grenzen der Sublayer liegt
    if mySublayer.contains(pointInLayer) {
        // Wenn der Punkt innerhalb der Sublayer liegt, kann man diese Ansicht oder eine andere zurückgeben
        // oder die notwendigen Aktionen ausführen.
        // In diesem Fall bestimmen wir, dass der Touch "auf" der Sublayer war.
        print("Touch auf mySublayer")
        // Man kann nil zurückgeben, wenn diese Ansicht den Touch nicht weiter verarbeiten soll, oder super.hitTest, um das Standardverhalten zu behalten.
    }
    
    // Standardmäßiges hitTest-Verhalten zulassen
    return super.hitTest(point, with: event)
}

Beispiel für die Verwendung der Koordinatenumwandlung im Gesten-Handler:

// In einer benutzerdefinierten UIView mit angehängtem UITapGestureRecognizer
@objc func handleTap(_ sender: UITapGestureRecognizer) {
    let tapLocationInView = sender.location(in: self)
    
    // Koordinaten des Taps in die Koordinaten der Sublayer umrechnen
    let tapLocationInSublayer = mySublayer.convert(tapLocationInView, from: layer!)
    
    // Prüfen, ob der Punkt innerhalb der Grenzen der Sublayer liegt
    if mySublayer.contains(tapLocationInSublayer) {
        print("Touch auf mySublayer")
        // Aktionen im Zusammenhang mit dem Touch auf der Sublayer ausführen
    }
}