emn.mun
emn.mun

Reputation: 447

iOS Custom annotations for MKMapView

First of all I'm using kingpin in order to display an array of annotations. Everything works just as expected.

My question is: How can I create a custom view for an annotation? And I'm not referring to replacing the image of MKPinAnnotationView.

            if (annotationView == nil) {
            annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"cluster"];
            annotationView.canShowCallout = YES;
            annotationView.image = [UIImage imageNamed:@"map_cluster"];
        }

With this I'm only able to replace the default pin with an Image. But this is not all I need.

http://imgur.com/nhUIvdx

I come from an Android background where I solved this problem by inflating a layout as a cluster (aka annotation in iOS). In this XML layout I'm positioning a container (the white frame), a picture and a counter. The result can bee seen in the picture below:

https://i.sstatic.net/dmbuL.jpg

How can I do this in iOS? Thanks in advance for any suggestions!

Upvotes: 1

Views: 256

Answers (2)

emn.mun
emn.mun

Reputation: 447

A quite late response, but I guess other people would still be interested

In a MKAnnotationView subclass:

First, define some dimensions:

#define ckImageHeight 65
#define ckImageWidth  55
#define kBorder 5

Then define the Annotation View's frame:

self.frame = CGRectMake(0, 0, ckImageWidth, ckImageHeight);

If you want the background to be an image and not just a color:

self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"map_checkin"]];

Then make a placeholder for the image

CGRect checkInPictureRect = CGRectMake(kBorder, kBorder, ckImageWidth - 9 , ckImageWidth - 9);
UIView *checkInPictureView = [[UIView alloc]initWithFrame:checkInPictureRect];

Then the fun starts:

// Crop image
UIImage *croppedImage = [ImageHelper centerCropImage:image];

// Resize image
CGSize checkInPictureSize = CGSizeMake(checkInPictureRect.size.width*1.5, checkInPictureRect.size.height*1.5);
UIGraphicsBeginImageContext(checkInPictureSize);
[croppedImage drawInRect:CGRectMake(0, 0, checkInPictureRect.size.width*1.5, checkInPictureRect.size.height*1.5)];
UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImageView *imageView = [[UIImageView alloc] initWithImage:resizedImage];
                            imageView.frame = checkInPictureView.bounds;
                            [checkInPictureView addSubview:imageView];
                            [self addSubview:checkInPictureView];

// Counter
UIView *counterView = [[UIView alloc]initWithFrame:CGRectMake(45, -2, 15, 15)];
counterView.opaque = YES;
(checkIn.isNow) ? [counterView setBackgroundColor:[UIColor enloopBlue]] : [counterView setBackgroundColor:[UIColor enloopGreen]];
counterView.layer.cornerRadius = 8;

self.counterLabel = [[UILabel alloc] init];
self.counterLabel.frame = CGRectMake(4, 2, 10, 10);

if (self.count >= 10) {
    counterView.frame = CGRectMake(45, -2, 18, 18);
    self.counterLabel.frame = CGRectMake(3, 3, 12, 12);
}

[self.counterLabel setTextColor:[UIColor whiteColor]];
[self.counterLabel setFont:[UIFont fontWithName: @"Trebuchet MS" size: 11.0f]];
[self.counterLabel setText:[[NSString alloc] initWithFormat:@"%lu", (unsigned long)self.count]];
[counterView addSubview:self.counterLabel];
[counterView bringSubviewToFront:self.counterLabel];
[self addSubview:counterView];

As for the centerCropImage helper, nothing special:

+ (UIImage *)centerCropImage:(UIImage *)image {
    // Use smallest side length as crop square length
    CGFloat squareLength = MIN(image.size.width, image.size.height);
    // Center the crop area
    CGRect clippedRect = CGRectMake((image.size.width - squareLength) / 2, (image.size.height - squareLength) / 2, squareLength, squareLength);

    CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
    UIImage * croppedImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return croppedImage;
}

I know there are quite a few things to improve, but untill then I hope it will help others. :)

Upvotes: 0

Adela Toderici
Adela Toderici

Reputation: 1112

Here you can find how to create a custom annotation: custom annotation for maps

If you have any question, you can ask me:)

Upvotes: 2

Related Questions