2012-03-26 16 views
2

Ich habe zwei Ansichten, von denen jede zwei Unteransichten enthält.UITouch auf überlappende UIViews

Die Treffererkennung funktioniert einwandfrei, solange sich die beiden oberen Ansichten nicht überschneiden. Daher kann ich Teilansicht A auf der linken Seite des Bildes unten berühren.

Sobald jedoch die beiden oberen Ansichten sich überlappen, gibt es keine Möglichkeit, dass die A-Ansicht Berührungen erhält, da Ansicht 1 "über" Ansicht 2 ist und die Berührung "isst".

Sowohl Ansicht 1 als auch Ansicht 2 erkennen Berührungen, da sie verschoben werden können, müssen daher Zwischensichten "dazwischen" erkennen und darauf reagieren.

Das bedeutet, dass meine zwei "Draufsichten" Erkennung sollte sagen: "Oh, warte eine Minute, vielleicht überlege ich eine andere Ansicht und sollte das Ereignis an sie übergeben, und nur eine Drag/Bewegung um nur zu starten wenn keine andere Ansicht "unter mir" ist.

Wie würde ich das tun? enter image description here

Edit: Dank jaydee3

Dies zunächst nicht arbeiten, was in eine unendliche Rekursion: jede Ansicht auf seine Geschwister aufzuschieben, die wiederum an die initiierende Ansicht aufschiebt zurück:

- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    UIView * hit = [super hitTest:point withEvent:event] ; 

    if (hit == self) { 
     for (UIView * sibling in self.superview.subviews) { 
      if (sibling != self) { 
       CGPoint translated = [self convertPoint:point toView:sibling] ; 
       UIView * other = [sibling hitTest:translated withEvent:event] ; 
       if (other) { 
        return other ; 
       } 
      } 
     } 
    } 

    return hit ; 
} 

Also, habe ich ein „gekennzeichnet Set“, um zu verfolgen, welche Ansicht bereits besucht worden war, und nun alle Werke :)

- (UIView *) hitTest: (CGPoint) point withEvent: (UIEvent *) event { 

    static NSMutableSet * markedViews = [NSMutableSet setWithCapacity:4] ; 

    UIView * hit = [super hitTest:point withEvent:event] ; 

    if (hit == nil) return nil ; 

    if (hit == self) { 
     for (UIView * sibling in hit.superview.subviews) { 
      if (sibling != hit) { 
       if ([markedViews containsObject:sibling]) { 
        continue ; 
       } 

       [markedViews addObject:sibling] ; 
       CGPoint translated = [hit convertPoint:point toView:sibling] ; 
       UIView * other = [sibling hitTest:translated withEvent:event] ; 
       [markedViews removeObject:sibling] ; 

       if (other) { 
        return other ; 
       } 
      } 
     } 
    } 

    return hit ; 
} 

Antwort

3

Erstellen Sie eine benutzerdefinierte Unterklasse für Ihre Ansicht (die die anderen beiden Unteransichten enthält) und überschreiben Sie die hitTest:-Methode dafür. Überprüfen Sie in dieser Methode, ob die hitTest-Ansicht eine der beiden Teilansichten ist, andernfalls geben Sie nil zurück. So werden alle Berührungen in Ihrer Umgebung ignoriert. Daraus ergibt sich ein Blick auf die darunter liegende Ansicht, die selbst damit umgehen kann.

// edit: (Sie erhalten die Ansicht hitTest von UIView* view = [super hitTest:withEvent:]; Aufruf.)

// edit2: dachte ich mehr von smth wie folgt aus: :)

- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    UIView * hit = [super hitTest:point withEvent:event] ; 

    if (hit == self) { 
     return nil; 
    } 

    return hit ; 
} 

;)

+0

bearbeitet meine Antwort .. vielleicht funktioniert das besser. – calimarkus

+0

Das würde nicht funktionieren, da dies verhindern würde, dass die Top-Ansichten irgendein Ereignis behandeln würden. In meiner bearbeiteten Frage habe ich den Code zur Verfügung gestellt, der jetzt funktioniert. Danke noch einmal. – verec

+0

Aah Ich wusste nicht, dass Sie auch diese Ansichten berühren müssen. gut. Bitte. – calimarkus