Voici mon code. Je souhaite ajouter ma propre vue d'accroche personnalisée au lieu de iOS par défaut. Je sais qu'il n'y a qu'une légende à gauche et une vue à droite, mais je dois ajouter un type d'infobulle de vue avec mon propre arrière-plan et ma propre étiquette.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *userAnnotationView = nil;
if ([annotation isKindOfClass:MKUserLocation.class])
{
userAnnotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"UserLocation"];
if (userAnnotationView == nil) {
userAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"UserLocation"];
}
else
userAnnotationView.annotation = annotation;
userAnnotationView.enabled = YES;
userAnnotationView.canShowCallout = YES;
userAnnotationView.image = [UIImage imageNamed:@"map_pin.png"];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0,0,141,108)];
view.backgroundColor = [UIColor clearColor];
UIImageView *imgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"toltip.png"]];
[view addSubview:imgView];
userAnnotationView.leftCalloutAccessoryView = view;
return userAnnotationView;
}
}
J'ai eu le même problème et j'ai fini par faire la chose suivante:
Lorsque je reçois un rappel de délégué mapView
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
(il est temps de montrer ma CalloutView personnalisée)
J'utilise la vue reçue comme paramètre * (MKAnnotationView ) view (qui est une vue pin) et ajoute simplement ma vue personnalisée à cette vue de broche en utilisant
[view addSubview:customView];
Il ajoutera votre vue personnalisée au-dessus de cette vue de broche, donc si nous voulons qu'elle soit au-dessus de la broche, nous devons changer la propriété du centre de vue personnalisée comme ceci:
CGRect customViewRect = customView.frame;
CGRect rect = CGRectMake(-customViewRect.size.width/2, -customViewRect.size.height-7, customViewRect.size.width, customViewRect.size.height);
customView.frame = rect;
[view addSubview:customView];
Dans mon cas, ça ressemble à ça
! NOTE:
Il y a cependant une mise en garde qui peut être facilement corrigée, votre vue personnalisée ignorera les événements tactiles , à cause de mapView travailler différemment avec les touches. Voici une solution rapide :
1) Sous-classe MKAnnotationView (ou MKPinAnnotationView dépend de ce dont vous avez besoin)
2) dans votre délégué mapView
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
utilisez votre sous-classe au lieu de MKAnnotationView/MKPinAnnotationView
) dans votre fichier .m de sous-classe, remplacez deux méthodes comme suit:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hitView = [super hitTest:point withEvent:event];
if (hitView != nil)
{
[self.superview bringSubviewToFront:self];
}
return hitView;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
CGRect rect = self.bounds;
BOOL isInside = CGRectContainsPoint(rect, point);
if(!isInside)
{
for (UIView *view in self.subviews)
{
isInside = CGRectContainsPoint(view.frame, point);
if(isInside)
break;
}
}
return isInside;
}
Tout est fait!
J'ai créé une bibliothèque pour afficher des légendes personnalisées.
Vous pouvez passer n'importe quelle vue personnalisée pour la légende! Il prend également en charge les événements pour UIControls.
À la meilleure réponse ci-dessus dans Swift
Cela peut économiser quelques minutes pour se réécrire.
!REMARQUE:
Il y a une mise en garde qui peut cependant être facilement corrigée, votre vue personnalisée ignorera les événements tactiles, car mapView fonctionne différemment avec les tactiles. Voici une solution rapide:
1) Sous-classe MKAnnotationView (ou MKPinAnnotationView dépend de ce dont vous avez besoin)
2) dans votre délégué mapView
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
utilisez votre sous-classe au lieu de MKAnnotationView/MKPinAnnotationView
3) dans votre fichier .m de sous-classe, remplacez deux méthodes comme suit:
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, withEvent: event)
if (hitView != nil)
{
self.superview?.bringSubviewToFront(self)
}
return hitView;
}
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
let rect = self.bounds
var isInside = CGRectContainsPoint(rect, point)
if(!isInside) {
for view in self.subviews {
isInside = CGRectContainsPoint(view.frame, point)
break;
}
}
return isInside
}
Voici le meilleur exemple de vue CallOut
http://www.cocoacontrols.com/platforms/ios/controls/gikanimatedcallout
http://www.cocoacontrols.com/platforms/ios/controls/multirowcalloutannotationview
Je viens de créer une légende personnalisée pour ma vue de carte, ce qui évite les problèmes de disparition de la légende lorsque vous appuyez dessus. Ici est un Gist avec les étapes que j'ai prises.
Vous pouvez utiliser cette bibliothèque. Il fournit également un modèle prêt à l'emploi pour la vue d'accroche. Ajoute des animations sympas et une vue d'ancrage pour vos vues personnalisées.