2011-12-27 3 views
8

J'ai actuellement une vue de la carte avec quelques annotations dessus. J'ai l'annotation avec des images personnalisées. Le problème que j'essaie de résoudre est la sensibilité des images. Quand j'essaie de les faire glisser, j'ai l'impression que je dois toucher le centre exact pour que je puisse me concentrer dessus. Y a-t-il un moyen de rendre les limites de toucher plus grandes?Comment rendre MKAnnotationView sensible au toucher?

Répondre

17

Pour ce faire, vous devez sous-classer MKAnnotationView pour créer votre propre personnalisé MKAnnotationView. Dans votre sous-classe, remplacez les fonctions suivantes:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    // Return YES if the point is inside an area you want to be touchable 
} 

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    // Return the deepest view that the point is inside of. 
} 

Ceci permet d'appuyer sur des vues interactives (telles que des boutons, etc.). L'implémentation par défaut dans MKAnnotationView n'est pas stricte sur pointInside et hitTest car elle permet d'envoyer à une annotation différente les presses réellement contenues dans une annotation. Pour ce faire, il détermine le centre d'annotation le plus proche du point de contact et envoie les événements à cette annotation, afin que les annotations rapprochées (chevauchement) ne se bloquent pas les unes les autres. Cependant, dans votre cas, vous voudrez probablement bloquer d'autres annotations si l'utilisateur doit sélectionner et faire glisser l'annotation la plus haute, donc la méthode ci-dessus est probablement celle que vous voulez, sinon elle vous mettra sur le bon chemin.

EDIT: On m'a demandé dans les commentaires pour un exemple d'implémentation de hitTest:withEvent: - Cela dépend exactement ce que vous essayez d'atteindre. La question originale suggérait de toucher et de faire glisser des images dans l'annotation alors que dans mon cas, j'ai des boutons dans l'annotation que je veux être interactif.Voici mon code:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    UIView* hitView = [super hitTest:point withEvent:event]; 
    if (hitView != nil) 
    { 
     // ensure that the callout appears above all other views 
     [self.superview bringSubviewToFront:self]; 

     // we tapped inside the callout 
     if (CGRectContainsPoint(self.resultView.callButton.frame, point)) 
     { 
      hitView = self.resultView.callButton; 
     } 
     else if (CGRectContainsPoint(self.resultView.addButton.frame, point)) 
     { 
      hitView = self.resultView.addButton; 
     } 
     else 
     { 
      hitView = self.resultView.viewDetailsButton; 
     } 
     [self preventSelectionChange]; 
    } 
    return hitView; 
} 

Comme vous pouvez le voir est assez simple - La mise en œuvre MKAnnotationView (appelé super sur la première ligne de ma mise en œuvre) ne retourne que la première (la plus externe) vue, il ne perce pas à travers la Voir la hiérarchie pour voir quelle sous-vue le toucher est réellement à l'intérieur. Dans mon cas, je vérifie simplement si le toucher est dans l'un des trois boutons et les renvoie. Dans d'autres circonstances, vous pouvez avoir un simple rectangle basé sur la hiérarchie ou des tests plus complexes, par exemple pour éviter les zones transparentes dans votre vue pour permettre aux touches de passer à travers ces parties. Si vous devez forer vers le bas, CGRectContainsPoint peut être utilisé de la même manière que je l'ai utilisé, mais n'oubliez pas de décaler vos points dans les coordonnées de la vue locale pour chaque niveau de vue que vous explorez. La méthode preventSelectionChange permet d'empêcher la sélection de mes annotations personnalisées. Je l'utilise comme une légende personnalisable/interactive à partir des broches de mappage, ce qui permet de conserver la broche correspondante plutôt que de permettre à la sélection de passer à cette annotation.

+0

Pourriez-vous implémenter la méthode hitTest s'il vous plaît? – Daniel

+0

Si je pouvais voter votre réponse à nouveau, je le ferais! Merci pour la mise à jour. – Daniel

+0

Salut à nouveau, que diriez-vous de pointInside: withEvent:? Est-ce là où vous proposez que CGRectContainsPoint soit implémenté? – Daniel

0

Je mis en œuvre quelque chose de similaire de la manière suivante

  1. Créer une sous-classe de la classe Gesture Recognizer qui gère des touches
  2. Créer une sous-classe de la classe UIImage, cette classe utilise la classe de reconnaissance pour gérer vos gestes
  3. Utilisez ce dans l'annotation

le geste sous-classe traitera vos reconnaisseur gestes si vous les effectuez à tout moment dans l'ima ge. Cela devrait vous aider.

nous tenir à jour sur si cette solution a fonctionné pour u ...

1

Est-ce que vous sous-classe MKAnnotationView ou avez-vous changé juste définir la propriété d'image de celui-ci?

Voici la documentation pour définir la propriété de l'image.

Discussion: Attribution d'une nouvelle image à cette propriété modifie également la taille du cadre de la vue afin qu'elle corresponde à la largeur et la hauteur de la nouvelle image. La position de l'image de la vue ne change pas.

Vérifiez la taille du cadre de votre vue d'annotation, sur laquelle votre objet peut recevoir des contacts.

0

La solution @jhabbott n'a jamais fonctionné pour moi, comme je l'ai mentionné here.

J'ai une image et une étiquette côte à côte. L'image a été montré par la mise en annotationview image propriété, et l'étiquette en ajoutant un UILabel

Je redirigée la méthode func point(inside:with:) au UILabel un (qui comprenait la zone d'image) et hitTest n'a retourné exactement le même point de vue que je cliqué sur le étiquette ou l'image. Mais cliquez sur l'étiquette ne produit aucun rappel ...

Enfin, j'ai fini en élargissant le cadre MKAnnotationView pour entourer l'étiquette + image, je mets annotationView.image-nil, et j'ai créé mon habitude UIImageView.

Parce que je voulais que le point d'ancrage au milieu de l'image, je devais mettre une coutume un:

self.frame = CGRect(x: 0, y: 0, width: 
self.myLabel.frame.width, height: self.myLabel.frame.height) 
self.centerOffset = CGPoint(x: self.frame.width/2, y: self.myImageView.frame.height/2) 

Je supprimé point(inside:with:) et hitTest(point:with:) qui l'emporte n'a rien fait.

Et maintenant, pour la première fois, ma vue d'annotation est complètement réactive.

Questions connexes