I have created a custom MKAnnotationView for User Location:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]]) {
if (navStatus == NavStatusHeadingEnabled) {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
locationView = [[CustomLocationView alloc] initWithAnnotation:annotation reuseIdentifier:@"locationIdentifier"];
return locationView;
}
}
return nil;
}
CustomLocationView.h
- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self != nil)
{
self.backgroundColor = [UIColor clearColor];
blueDot = [UIImage imageNamed:@"userLocationDot.png"].CGImage;
CGImageRetain(blueDot);
CGPoint blueDotCenter = CGPointMake((self.frame.size.width - (CGImageGetWidth(blueDot) / 2)) / 2, (self.frame.size.height - (CGImageGetHeight(blueDot) / 2)) / 2);
blueDotLayer = [CALayer layer];
blueDotLayer.frame = CGRectMake(blueDotCenter.x, blueDotCenter.y , CGImageGetWidth(blueDot) / 2, CGImageGetHeight(blueDot) / 2);
blueDotLayer.contents = (id)blueDot;
blueDotLayer.shadowOpacity = 0.4;
blueDotLayer.shadowColor = [UIColor blackColor].CGColor;
blueDotLayer.shadowOffset = CGSizeMake(0.4, 0.3);
blueDotLayer.shadowRadius = 1.0f;
[self.layer insertSublayer:blueDotLayer above:self.layer];
}
return self;
}
- (void)setAnnotation:(id <MKAnnotation>)annotation
{
[super setAnnotation:annotation];
[self setNeedsDisplay];
}
- (void)dealloc {
[blueDotLayer release];
[super dealloc];
}
The problem is it just stays on the same place and not moving like the blue dot. What I am doing wrong?
Thanks Bill.
I ran into this problem just now as well. I'm not sure if this is expected behavior or not, but for whatever reason it is up to us to move our custom MKUserLocation annotation views.
A naive solution is
- (void) locationController: (LocationController *) locationController
didUpdateToLocation: (CLLocation *) location
{
[[self mapView] setShowsUserLocation:NO];
[[self mapView] setShowsUserLocation:YES];
}
But this makes the current location annotation jump around the screen which I found undesirable.
Better yet is to keep a reference to the custom annotation view as an ivar in your view controller and then do:
- (void) locationController: (LocationController *) locationController
didUpdateToLocation: (CLLocation *) location
{
CGPoint newCenterPoint = [[self mapView] convertCoordinate:[location coordinate] toPointToView:[[self customAnnotationView] superview]];
newCenterPoint.x += [[self customAnnotationView] centerOffset].x;
newCenterPoint.y += [[self customAnnotationView] centerOffset].y;
[UIView animateWithDuration:0.3f animations:^{
[[self customAnnotationView] setCenter:newCenterPoint];
}];
}
This is good except when you change the zoom level the annotation stays where it was relative to the map view's rect and then animates to the correct location only after the zoom or pan is complete. Best to follow Apple's lead and make the current location annotation disappear and reappear during region changes:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
[[self mapView] setShowsUserLocation:NO];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
[[self mapView] setShowsUserLocation:YES];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With