How do I change the frame position for a custom MKAnnotationView?

13,683

Solution 1

Rather than subclass MKAnnotationView, have you tried using a generic MKAnnotationView and setting the image and centerOffset properties?

Solution 2

I tried using centerOffset and for some reason the image was in the right position when zoomed in, but as you zoomed the map out the image would move away from where it was supposed to be. The fix to this was setting the image frame with the offset. Here's the code I used (You can leave out the callout stuff if you don't have a callout), I used the pins from here)

#pragma mark MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    if(![annotation isKindOfClass:[MyAnnotation class]]) // Don't mess user location
        return nil;

    MKAnnotationView *annotationView = [aMapView dequeueReusableAnnotationViewWithIdentifier:@"spot"];
    if(!annotationView)
    {
        annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"spot"];
        annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [(UIButton *)annotationView.rightCalloutAccessoryView addTarget:self action:@selector(openSpot:) forControlEvents:UIControlEventTouchUpInside];
        annotationView.enabled = YES;
        annotationView.canShowCallout = YES;
        annotationView.centerOffset = CGPointMake(7,-15);
        annotationView.calloutOffset = CGPointMake(-8,0);
    }

    // Setup annotation view
    annotationView.image = [UIImage imageNamed:@"pinYellow.png"]; // Or whatever

    return annotationView;
}

Adjust centerOffset and calloutOffset as needed to suit your image, and desired center point, and callout point.

Solution 3

Your UIAnnotationView is always drawn at the same scale, the map's zoom level doesn't matter. That's why centerOffset isn't bound with the zoom level.

annView.centerOffset is what you need. If you see that your pin is not at the good location (for example, the bottom center move a little when you change the zoom level), it's because you didn't set the right centerOffset.

By the way, if you want to set the point of the coordinate at the bottom center of the image, the x coordinate of your centerOffset should be 0.0f, as annotationView center the image by default. So try :

annView.centerOffset = CGPointMake(0, -imageHeight / 2);

Answer from [MKAnnotation image offset with custom pin image

Share:
13,683
andrei
Author by

andrei

Updated on June 11, 2022

Comments

  • andrei
    andrei almost 2 years

    I am trying to make a custom annotation view by subclassing MKAnnotationView and overriding the drawRect method. I want the view to be drawn offset from the annotation's position, somewhat like MKPinAnnotationView does it, so that the point of the pin is at the specified coordinates, rather than the middle of the pin. So I set the frame position and size as shown below. However, it doesn't look like I can affect the position of the frame at all, only the size. The image ends up being drawn centered over the annotation position. Any tips on how to achieve what I want?

    MyAnnotationView.h:

    @interface MyAnnotationView : MKAnnotationView {
    
    }
    

    MyAnnotationView.m:

    - (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
        if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
            self.canShowCallout = YES;
            self.backgroundColor = [UIColor clearColor];
            // Position the frame so that the bottom of it touches the annotation position 
            self.frame = CGRectMake(0, -16, 32, 32);
        }
        return self;
    }
    
    - (void)drawRect:(CGRect)rect {
        [[UIImage imageNamed:@"blue-dot.png"] drawInRect:rect];
    }