web-dev-qa-db-fra.com

Comment ajouter une vue personnalisée dans la légende d'annotation de la carte

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;
        }

}

Image for reference

32
Gaurav

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

enter image description here

! 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!

133
haawa

J'ai créé une bibliothèque pour afficher des légendes personnalisées.

DXCustomCallout-ObjC

Vous pouvez passer n'importe quelle vue personnalisée pour la légende! Il prend également en charge les événements pour UIControls.

Custom Callout

10
Selvin

À 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
}
2
andreylanadelrey
1
iPatel

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.

1
bryguy1300

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.

https://github.com/okhanokbay/MapViewPlus

enter image description hereenter image description here

0