Z-index of iOS MapKit user location annotation

后端 未结 9 2290
天命终不由人
天命终不由人 2020-12-13 07:12

I need to draw the current user annotation (the blue dot) on top of all other annotations. Right now it is getting drawn underneath my other annotations and getting hidden.

相关标签:
9条回答
  • 2020-12-13 07:20

    Here is a way to do it using predicates. I think it should be faster

    NSPredicate *userLocationPredicate = [NSPredicate predicateWithFormat:@"class == %@", [MKUserLocation class]];
    NSArray* userLocation = [[self.mapView annotations] filteredArrayUsingPredicate:userLocationPredicate];
    
    if([userLocation count]) {
        NSLog(@"Bring blue location dot to front");
        MKAnnotationView *view = [self.mapView viewForAnnotation:(MKUserLocation *)[userLocation objectAtIndex:0]];
        [[view superview] bringSubviewToFront:view];
    }
    
    0 讨论(0)
  • 2020-12-13 07:28

    Try, getting a reference to the user location annotation (perhaps in mapView: didAddAnnotationViews:) and then bring that view to the front of the mapView after all of your annotations have been added.

    0 讨论(0)
  • 2020-12-13 07:32

    Finally got it to work using the code listed below thanks to the help from Paul Tiarks. The problem I ran into is that the MKUserLocation annotation gets added to the map first before any others, so when you add the other annotations their order appears to be random and would still end up on top of the MKUserLocation annotation. To fix this I had to move all the other annotations to the back as well as move the MKUserLocation annotation to the front.

    - (void) mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views 
    {
        for (MKAnnotationView *view in views) 
        {
            if ([[view annotation] isKindOfClass:[MKUserLocation class]]) 
            {
                [[view superview] bringSubviewToFront:view];
            } 
            else 
            {
                [[view superview] sendSubviewToBack:view];
            }
        }
    }
    

    Update: You may want to add the code below to ensure the blue dot is drawn on top when scrolling it off the viewable area of the map.

    - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
    {        
      for (NSObject *annotation in [mapView annotations]) 
      {
        if ([annotation isKindOfClass:[MKUserLocation class]]) 
        {
          NSLog(@"Bring blue location dot to front");
          MKAnnotationView *view = [mapView viewForAnnotation:(MKUserLocation *)annotation];
          [[view superview] bringSubviewToFront:view];
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-13 07:32

    Another solution: setup annotation view layer's zPosition (annotationView.layer.zPosition) in:

    - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;

    0 讨论(0)
  • 2020-12-13 07:33

    Just use the .layer.anchorPointZ property.

    Example:

     func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
            views.forEach {
                if let _ = $0.annotation as? MKUserLocation {
                    $0.layer.anchorPointZ = 0
                } else {
                    $0.layer.anchorPointZ = 1
                }
            }
        }
    

    Here is there reference https://developer.apple.com/documentation/quartzcore/calayer/1410796-anchorpointz

    0 讨论(0)
  • 2020-12-13 07:33

    Using Underscore.m

    _.array(mapView.annotations).
        filter(^ BOOL (id<MKAnnotation> annotation) { return [annotation 
    isKindOfClass:[MKUserLocation class]]; })
        .each(^ (id<MKAnnotation> annotation) { [[[mapView 
    viewForAnnotation:annotation] superview] bringSubviewToFront:[mapView 
    viewForAnnotation:annotation]]; });
    
    0 讨论(0)
提交回复
热议问题