Search code examples
iosmapkitmkannotationview

MKAnnotationView with custom view and image view


In my Map application, instead of showing a pin, I want to show a colored background circle with image in it. The color of the background (which is shade of green in below image) circle is dynamic. It will look as in below image:

enter image description here

I created TCircleView which draws the color in "drawRect"

To show similar annotation, I created object of TCircleView and UIImageView and add them to MKAnnotationView object. Its looking good and visible as expected.

But its not allowing to detect tap/touch to show the call out.

I'm using the below code:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {

    if ([annotation isKindOfClass:[MKPointAnnotation class]]) {
        return nil;
    }

    static NSString *annotationIdentifier = @"StickerPin";

    MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];

    if (!annotationView) {
        annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
        annotationView.canShowCallout = YES;
    }

    TCircleView* circleView = [[TCircleView alloc] init];
    circleView.green = [postObj[@"severity"] floatValue]; //dynamic value coming from server

    UIImageView* imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Piano"]];

    CGRect r = imgView.frame;
    r.size.height = r.size.width = 60;
    imgView.frame = r;
    circleView.frame = r;

    [annotationView addSubview:circleView];
    [annotationView addSubview:imgView];

    return annotationView;
}

Its not allowing to show the callout or not even calling the delegate "didSelectAnnotationView:"
How to show the custom view as annotation on the map?


Solution

  • I created a sub class of annotation view and achieved it. The code is below:

    @interface TStickerAnnotationView : MKAnnotationView
    
    @property(nonatomic) float stickerColor;
    
    @end
    
    @interface TStickerAnnotationView () {
        UIImageView *_imageView;
        TCircleView *_circleView;
    }
    
    
    @end
    
    @implementation TStickerAnnotationView
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // make sure the x and y of the CGRect are half it's
            // width and height, so the callout shows when user clicks
            // in the middle of the image
            CGRect  viewRect = CGRectMake(-30, -30, 60, 60);
    
            TCircleView* circleView = [[TCircleView alloc] initWithFrame:viewRect];
            _circleView = circleView;
            [self addSubview:circleView];
    
            UIImageView* imageView = [[UIImageView alloc] initWithFrame:viewRect];
    
            // keeps the image dimensions correct
            // so if you have a rectangle image, it will show up as a rectangle,
            // instead of being resized into a square
            imageView.contentMode = UIViewContentModeScaleAspectFit;
    
            _imageView = imageView;
    
            [self addSubview:imageView];
    
    
    
        }
        return self;
    }
    
    - (void)setImage:(UIImage *)image
    {
        // when an image is set for the annotation view,
        // it actually adds the image to the image view
        _imageView.image = image;
    }
    
    - (void)stickerColor:(float)color {
        _circleView.green = color;
        [_circleView setNeedsDisplay];
    }