How to customize the callout bubble for MKAnnotationView?
There is an even easier solution.
Create a custom UIView
(for your callout).
Then create a subclass of MKAnnotationView
and override setSelected
as follows:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if(selected)
{
//Add your custom view to self...
}
else
{
//Remove your custom view...
}
}
Boom, job done.
detailCalloutAccessoryView
In the olden days this was a pain, but Apple has solved it, just check the docs on MKAnnotationView
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.detailCalloutAccessoryView = UIImageView(image: UIImage(named: "zebra"))
Really, that's it. Takes any UIView.
Continuing on from @TappCandy's brilliantly simple answer, if you want to animate your bubble in the same way as the default one, I've produced this animation method:
- (void)animateIn
{
float myBubbleWidth = 247;
float myBubbleHeight = 59;
calloutView.frame = CGRectMake(-myBubbleWidth*0.005+8, -myBubbleHeight*0.01-2, myBubbleWidth*0.01, myBubbleHeight*0.01);
[self addSubview:calloutView];
[UIView animateWithDuration:0.12 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^(void) {
calloutView.frame = CGRectMake(-myBubbleWidth*0.55+8, -myBubbleHeight*1.1-2, myBubbleWidth*1.1, myBubbleHeight*1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 animations:^(void) {
calloutView.frame = CGRectMake(-myBubbleWidth*0.475+8, -myBubbleHeight*0.95-2, myBubbleWidth*0.95, myBubbleHeight*0.95);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.075 animations:^(void) {
calloutView.frame = CGRectMake(-round(myBubbleWidth/2-8), -myBubbleHeight-2, myBubbleWidth, myBubbleHeight);
}];
}];
}];
}
It looks fairly complicated, but as long as the point of your callout bubble is designed to be centre-bottom, you should just be able to replace myBubbleWidth
and myBubbleHeight
with your own size for it to work. And remember to make sure your subviews have their autoResizeMask
property set to 63 (i.e. "all") so that they scale correctly in the animation.
:-Joe
Found this to be the best solution for me. You'll have to use some creativity to do your own customizations
In your MKAnnotationView
subclass, you can use
- (void)didAddSubview:(UIView *)subview{
int image = 0;
int labelcount = 0;
if ([[[subview class] description] isEqualToString:@"UICalloutView"]) {
for (UIView *subsubView in subview.subviews) {
if ([subsubView class] == [UIImageView class]) {
UIImageView *imageView = ((UIImageView *)subsubView);
switch (image) {
case 0:
[imageView setImage:[UIImage imageNamed:@"map_left"]];
break;
case 1:
[imageView setImage:[UIImage imageNamed:@"map_right"]];
break;
case 3:
[imageView setImage:[UIImage imageNamed:@"map_arrow"]];
break;
default:
[imageView setImage:[UIImage imageNamed:@"map_mid"]];
break;
}
image++;
}else if ([subsubView class] == [UILabel class]) {
UILabel *labelView = ((UILabel *)subsubView);
switch (labelcount) {
case 0:
labelView.textColor = [UIColor blackColor];
break;
case 1:
labelView.textColor = [UIColor lightGrayColor];
break;
default:
break;
}
labelView.shadowOffset = CGSizeMake(0, 0);
[labelView sizeToFit];
labelcount++;
}
}
}
}
And if the subview
is a UICalloutView
, then you can screw around with it, and what's inside it.