Touch bei überlappenden ImageViews

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Touch bei überlappenden ImageViews

    Hi!
    Ich bastel mir gerade ein kleines Spielchen... Hierbei habe ich ein Feld von ImageViews, welche PNG-Grafiken enthalten, die sechseckige Felder darstellen (der Rest der Grafik ist transparent). Diese ImageViews überlappen sich - und ich möchte nun, wenn ein Touch registriert wird, herausfinden, welcher ImageView gemeint war. Der nicht-gemeinte View ist an dieser Stelle ja transparent, also dachte ich mir, dass man vielleicht den Alpha-Wert an dieser Stelle lesen könnte und anhand dessen dann entscheiden. Nur finde ich nirgends in der Doku passende Funktionen dazu (bin alle UIImage, UIImageView- und CG-Funktionen durchgegangen). -- Ein anderer Ansatz wäre, mit den CG-Funktionen einen Pfad zu erstellen, der die Sechseck-Form abbildet, und dann schauen, ob der Touch da drin ist, aber ich bekomme den Touch nicht von dem globalen View auf den Offset innerhalb der Zelle übertragen.
    Habt ihr eine Idee?

    Momentan ist das einfach so (ohne Prüfung; nimmt einfach die "obere" Zelle...)

    Quellcode

    1. // (GameViewController.m)
    2. // Handles the end of a touch
    3. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    4. {
    5. // Enumerate through all the touch objects.
    6. for (UITouch *touch in touches) {
    7. [self dispatchFirstTouchAtPoint:[touch locationInView:self.view] forEvent:nil];
    8. }
    9. }
    10. -(void) dispatchFirstTouchAtPoint:(CGPoint)touchPoint forEvent:(UIEvent *)event
    11. {
    12. UIImageView *cell;
    13. for(int i = 101; i <= 119; i++) { // Die Felder haben Tags von 101 bis 119
    14. cell = (UIImageView *)[self.view viewWithTag:i];
    15. if (CGRectContainsPoint([cell frame], touchPoint)) {
    16. [self clickOnCell:i];
    17. break; // nach der ersten passenden zelle aufhören
    18. }
    19. }
    20. }
    Alles anzeigen


    Achja, die Sechseck-Grafiken sehen so aus:

    [Blockierte Grafik: http://ablage.ptec-media.de/uploads/hexagon.png]

    Besten Dank! Ich hoffe ihr versteht, was ich will ;)
  • Wenn ich dein Problem richtig verstehe, brauchst du eigentlich "nur" eine Funktion HexagonContainsPoint(...) schreiben, die du in deiner Dispatcher-Funktion statt CGRectContainsPoint verwendest.

    In HexagonContainsPoint kannst du ja erst mal damit anfangen mit CGRectContainsPoint zu prüfen, ob es überhaupt annähernd das korrekte Sechseck ist. Wenn ja, sollte es mit einigermaßen einfach sein, per simpler Trigonometrie zu prüfen, ob der Touch in einer der vier "leeren Ecken" war (bzw. eben nicht), die das Quadrat, das durch "frame" beschrieben wird, zu einem Sechseck machen. Schließlich handelt es sich um einfache rechtwicklige Dreiecke.


    Eine Nebenbemerkung: Da du die Image-Views lediglich zur Anzeige der Sechecke verwendest (und nicht z.B. zur Touch-Erkennung), solltest du statt UIImageViews besser CALayer verwenden. Die sind wesentlich "leichtgewichtiger" und damit Schwergewichten wie UIImageView vorzuziehen, falls man nicht UIView-spezifische Funktionen braucht.

    Das Handling von CALayers ist dem von Views recht ähnlich.
    Hier ein Beispiel für das Anlegen eines Layers zur Anzeige eines PNG-Bilds:

    Quellcode

    1. CALayer* sechseck = [CALayer layer];
    2. sechseck.anchorPoint = CGPointMake (0.5, 0.5);
    3. sechseck.frame = CGRectMake(...); // Position im superlayer
    4. sechseck.contents = (UIImage*)[UIImage imageNamed:@"sechseck.png"].CGImage;
    5. [spielFlaecheView.layer addSublayer:sechseck];
    Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
    Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
  • Ah, hat geklappt.
    Eigentlich hatte ich nur übersehen, dass man der locationInView:-Methode ja auch den ImageView geben kann... und dann scheint es jetzt mit dem Pfad doch zu funktionieren.

    Quellcode

    1. -(BOOL)hexagon:(UIImageView *)cell containsTouch:(UITouch *)touch
    2. {
    3. // check if touch is in the view
    4. if (CGRectContainsPoint([cell frame], [touch locationInView:self.view]) )
    5. {
    6. //check if touch is not outside the hexagon
    7. CGPoint point = [touch locationInView:cell];
    8. CGMutablePathRef path;
    9. path = CGPathCreateMutable();
    10. CGPathMoveToPoint(path, NULL, 20, 0);
    11. CGPathAddLineToPoint(path, NULL, 55, 0);
    12. CGPathAddLineToPoint(path, NULL, 75, 32);
    13. CGPathAddLineToPoint(path, NULL, 55, 65);
    14. CGPathAddLineToPoint(path, NULL, 20, 65);
    15. CGPathAddLineToPoint(path, NULL, 0, 32);
    16. CGPathAddLineToPoint(path, NULL, 20, 0);
    17. return CGPathContainsPoint(path, NULL,point,NO);
    18. } else return NO;
    19. }
    Alles anzeigen


    Das mit dem Layer werd ich dann auch mal ausprobieren...
    Danke!

    Gruß