MKUserLocation Custom View not moving!
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];
开发者_StackOverflow中文版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];
}
Bill,
You need a CLLocationManager that has been initialized with an applicable desiredAccuracy and distanceFilter and then implement the applicable delegate methods, and set your own code as the delegate on the locationManager instance.
At a minimum you should have the following method which the Location Manager will call once it has determined the current location with in the desiredAccuracy and then again whenever the distanceFilter has been met.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation ;
Cheers, Mack
I just found an answer for this problem. My code is in Monotouch, but it should be easy to re-do the same in ObjC.
to show customized image over default MKUserLocation
we need to add a subview on top of the original one. to do this, override DidAddAnnotationViews
in MKMapView
delegate
void DidAddAnnotationViews (object sender, MKMapViewAnnotationEventArgs e)
{
MKAnnotationView v = mapView.ViewForAnnotation(mapView.UserLocation);
if(v != null)
{
if(v.Subviews.Count() == 0)
{
UIImageView iv = new UIImageView(new RectangleF(0,0, 22, 22));
iv.Image = UIImage.FromFile("res/pins/Yhere.png");
v.AddSubview(iv);
v.BringSubviewToFront(iv);
}
}
}
This gives custom image moving on top of blue dot. more over, user tracking and location updates features works perfectly and you still can see blue circles that indicate location accuracy.
Have fun customizing MKUserLocation!
Here is the answer from Apple Developer Technical Support
I just finished talking to the MapKit engineers and they confirmed that this is a bug in iOS. My test app is experiencing the same problem.
I don't know if this was fixed in iOS 6, the answer is for the iOS 5.
精彩评论