6
votes

Intercepter / Hijacking iPhone Touch Events pour MKAPView

Y a-t-il un bug dans la 3,0 SDK qui désactive le zoom en temps réel et interceptant le geste de zoom-in pour la MKMAPView? J'ai un vrai code simple pour que je puisse détecter des événements de Tap, mais il y a deux problèmes:

  1. Le geste de zoom-in est toujours interprété comme un zoom-out
  2. Aucun des gestes de zoom met à jour la vue de la carte en temps réel.

    in Hittest, si je retourne la vue "Carte", la fonctionnalité MKMapView fonctionnait bien, mais je n'ai pas la possibilité d'intercepter les événements.

    Des idées?

    myMapView.h: xxx

    mymapview.m: xxx


0 commentaires

6 Réponses :


0
votes

MKMAPView ne répond pas aux méthodes tactiles énumérées ci-dessus ...


5 commentaires

Je ne crois pas ça. Les casseroles de la carte et zooment OK en passant les événements à la vue Carte. Lorsque "Carte" est remplacé par "Super", la carte n'a absolument aucune interactivité. L'ensemble du framework de Mapkit ressemble un peu à l'OMI à moitié fait. Il y a ce problème et il devrait y avoir une méthode de rappel dans le MapViewelegate pour l'annotation sélectionnée.


Pour autant que je sache, un groupe de pommes personnalisées UIS telle (Uiscrollview, mkmapview) ne vous laissez pas avoir la main sur les événements tactiles. Je pense qu'il y a une méthode de rappel dans MapViewelegate pour une annotation sélectionnée ...


Bien sûr, il répond aux touches, cela n'offre tout simplement pas un moyen de les intercepter à moins que vous n'en hérite ou de l'envelopper


Je n'ai pas dit que cela n'a pas répondu aux touches, j'ai dit qu'il ne répond pas aux méthodes tactiles énumérées ci-dessus, ce qui signifie que vous ne pouvez pas intercepter les touches ...


Et BTW introuvant de MKMAPView ne vous permet pas d'intercepter des touches non plus



1
votes

Essayez

[Super Touchrésended: touche windevent: événement];

au lieu de

[carte touchante: touche windevent: événement];

et appliquer cette idée à toutes les méthodes d'événement tactile. De cette façon, les touches devraient déployer la chaîne du répondeur et la paix sera restaurée.


0 commentaires

5
votes

J'ai eu le même problème - je voulais dessiner des échelles de carte au-dessus de la vue Carte. Pour le faire, je devais intercepter les événements tactiles, puis les renvoyer à la vue Carte. Malheureusement, lorsque le MKMAPView n'est pas le récepteur d'origine des événements, certaines animations de panoramique et de zoom en douceur ne fonctionnent plus.

Cependant, j'ai trouvé une solution à ce problème - un peu hacky mais fonctionne: 1. J'ai mis mes Mapscales UIView au-dessus de MKMAPView et avons désactivé les événements de réception, de sorte que la sous-jacente MKMAPView ait reçu les événements par défaut. 2. J'ai sous-classé uiwindow avec la classe MyMainWindow et j'ai remplacé la méthode: xxx

  1. J'ai fait la fenêtre principale de ma candidature un instasnce de MyMainWindow.

    De cette manière, mon composant Mapscales reçoit et peut réagir à tous les événements tactiles et, en même temps, il ne s'agit pas du MKMapView sous-jacent :)


4 commentaires

Ce n'est pas un hack. C'est la bonne façon de résoudre ce problème. Composition, pas héritage. juste parce que vous pouvez hériter de mkmapview ne signifie pas que vous devriez


Comment faites-vous cela lorsque la carte n'est pas la seule vue de la fenêtre, c'est-à-dire que vous avez une barre de navigation ou quelque chose. Vous ne voulez pas que les clics dans la barre de navigation se repoussent vers les Mapscales. Est le seul moyen de vérifier la taille?


une autre manière codée moins dure .... @property (nonatomic, assignez) ID Tapdelegate; Si (Tapdelegate == nil) retour; Nsset * touche = [événement Alltouches]; si (touche.Count! = 1) retour; Uitouch * toucher = [touche n'importe quoi]; if (tact.tapcount == 2 && toucher.phase == utituchPhaseended) {[Tapdelegate touché: toucher]; }


Un peu plus de code ici irait un long chemin à expliquer mieux les choses.



1
votes

Pour étendre la réponse de @ Chomasek, afin de traiter uniquement ces touches pour la vue Carte, je suis ce qui suit:

  1. Donnez à la carte une balise, comme 99 li>
  2. Lorsque je me touche, parcourez la hiérarchie de la vue de la vue de réception, à la recherche d'une vue avec la balise ci-dessus. Li> ol>

    Voici le code: p> xxx pré>

    puis dans SendEvent: code> p>

    // this does into the UIWindow subclass
    BOOL isMapView = NO;    
    UIView* superView = touch.view.superview;
    while(superView)
    {
        //Debug(@"superView = %@", superView);
        if (superView.tag == kICTagForMapView)
        {
            isMapView = YES;
            break;
        }
        superView = superView.superview;
    }
    
    if (isMapView == NO) return;
    
    // do stuff here
    


0 commentaires

2
votes
#import <UIKit/UIKit.h>
#import "UIViewTouch.h"
#import <MapKit/MapKit.h>

@interface MapTouchAppDelegate : NSObject <UIApplicationDelegate>
{
    UIViewTouch *viewTouch;
    MKMapView *mapView;
    UIWindow *window;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) UIViewTouch *viewTouch;
@property (nonatomic, retain) MKMapView *mapView;

@end


#import "MapTouchAppDelegate.h"

@implementation MapTouchAppDelegate

@synthesize window;
@synthesize viewTouch;
@synthesize mapView;

- (void)applicationDidFinishLaunching:(UIApplication *)application
{    
    //We create a view wich will catch Events as they occured and Log them in the Console
    viewTouch = [[UIViewTouch alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];

    //Next we create the MKMapView object, which will be added as a subview of viewTouch
    mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
    [viewTouch addSubview:mapView];

    //And we display everything!
    [window addSubview:viewTouch];
    // Override point for customization after application launch
    [window makeKeyAndVisible];
}


- (void)dealloc {
    [window release];
    [super dealloc];
}

#import <UIKit/UIKit.h>


@interface UIViewTouch : UIView
{
    UIView *viewTouched;
}
@property (nonatomic, retain) UIView * viewTouched;

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

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

@end


#import "UIViewTouch.h"


@implementation UIViewTouch

@synthesize viewTouched;

//The basic idea here is to intercept the view which is sent back as the firstresponder in hitTest.
//We keep it preciously in the property viewTouched and we return our view as the firstresponder.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{
    NSLog(@"Hit Test");
    self.multipleTouchEnabled = true;
    viewTouched = [super hitTest:point withEvent:event];
    return self;
}

//Then, when an event is fired, we log this one and then send it back to the viewTouched we kept, and voilà!!! :)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    NSLog(@"Touch Began");

    [viewTouched touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touch Moved");
    [viewTouched touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{
    NSLog(@"Touch Ended");
    [viewTouched touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touch Cancelled");
}


@end
This code will detect touches as well as zooming.

0 commentaires

8
votes

Le meilleur moyen que j'ai trouvé pour atteindre cela est avec un reconnaissance de geste. On ne sait pas si vous voulez reconnaître les événements de zoom vous-même ou simplement détecter lorsque l'utilisateur est en zoom avant / panoramique.

Je n'ai pas besoin de détecter une casserole ou un zoom de carte - je vous souciez de mettre un doigt n'importe où l'utilisateur dans le mkapview. Si vous devez détecter le zoom ou le panneau avec 100% de rappel et de précision, cela pourrait être plus compliqué que cela. Ce dont nous avons vraiment besoin est une implémentation open source de mkapView afin que nous puissions ajouter ceci au délégué, parmi de nombreuses autres fonctionnalités. P>

Voici ce que je fais: implémenter un reconnaissance de geste qui ne peut pas être empêché et qui ne peut pas empêcher les autres reconnaissants de geste. Ajoutez-le à la vue Carte et gérez les événements tactiles pertinents comme vous le souhaitez. P>

Comment détecter tout robinet à l'intérieur d'un MKMAPView (sans astuces) H2>
//
//  WildcardGestureRecognizer.m
//  Created by Raymond Daly on 10/31/10.
//  Copyright 2010 Floatopian LLC. All rights reserved.
//

#import "WildcardGestureRecognizer.h"


@implementation WildcardGestureRecognizer
@synthesize touchesBeganCallback;

-(id) init{
 if (self = [super init])
 {
  self.cancelsTouchesInView = NO;
 }
 return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
 if (touchesBeganCallback)
  touchesBeganCallback(touches, event);
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}

- (void)reset
{
}

- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
{
}

- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
{
 return NO;
}

- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
{
 return NO;
}

@end


3 commentaires

Exactement ce que je cherchais, merci pour ça! N'oubliez-vous pas si j'utilise votre wildcardGesturerecognizer dans ma bibliothèque open source qui vise à simplifier la manipulation de MapKit (c'est à un état de début, mais je prévois de l'étendre avec de plus en plus de fonctionnalités)? Github.com/myell0w/mtlocatemeBarbuttonitem


Fonce. Je le relâche dans le domaine public


Devrait-il détecter les événements PAN / ZOOM? Je ne peux pas voir passer les événements à mon MKMapView.