iOS MapKit用户位置注释的Z-index

时间:2011-08-22 01:30:30

标签: objective-c ios mapkit

我需要在所有其他注释之上绘制当前用户注释(蓝点)。现在它正在我的其他注释下面被隐藏起来。我想调整此注释视图的z-index(蓝点)并将其置于顶部,是否有人知道如何?

更新 所以我现在可以获得MKUserLocationView的处理,但是我该如何推进呢?

- (void) mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views {
    for (MKAnnotationView *view in views) {
        if ([[view annotation] isKindOfClass:[MKUserLocation class]]) {
            // How do I bring this view to the front of all other annotations?
            // [???? bringSubviewToFront:????];
        }
    }
}

9 个答案:

答案 0 :(得分:34)

Paul Tiarks的帮助下,最后使用下面列出的代码使其工作。我遇到的问题是MKUserLocation注释首先被添加到地图之前,所以当你添加其他注释时,它们的顺序似乎是随机的,并且最终仍然会在MKUserLocation注释之上。为了解决这个问题,我必须将所有其他注释移到后面,并将MKUserLocation注释移到前面。

- (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];
        }
    }
}

更新:您可能需要添加以下代码,以确保在将其从地图的可视区域滚动时在顶部绘制蓝点。

- (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];
    }
  }
}

答案 1 :(得分:25)

另一个解决方案: 在:

中设置注释视图图层的zPosition(annotationView.layer.zPosition

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

答案 2 :(得分:9)

该线程的官方答案是错误的......使用zPosition确实是最好的方法,使用regionDidChangeAnimated是最快的...

否则你会在地图上的许多注释遭受巨大的性能影响(因为每次帧的更改都会重新扫描所有注释)。并一直在测试......

所以在创建注释视图时(或在didAddAnnotationViews中)设置:         self.layer.zPosition = -1; (低于所有其他人)

正如yuf所指出的那样:    这使得引脚覆盖了其他引脚的标注 - yuf于2013年12月5日20:25

即。注释视图将显示在其他引脚下方。

要修复,只需在选择时将zPosition重新设置为0

-(void) mapView:(MKMapView*)mapView didSelectAnnotationView:(MKAnnotationView*)view {
    if ([view isKindOfClass:[MyCustomAnnotationView class]])
        view.layer.zPosition = 0;
   ...
}

-(void) mapView:(MKMapView*)mapView didDeselectAnnotationView:(MKAnnotationView*)view {
    if ([view isKindOfClass:[MyCustomAnnotationView class]])
        view.layer.zPosition = -1;
   ...
}

答案 3 :(得分:2)

尝试获取对用户位置标注的引用(可能在mapView: didAddAnnotationViews:中),然后在添加完所有注释后将该视图放到mapView的前面。

答案 4 :(得分:2)

iOS 14更新

我知道这是一篇过时的文章,但是该问题仍然适用,您在将其输入到您喜欢的搜索引擎中时会在这里结束。

从iOS 14,Apple introduced a zPriority property to MKAnnotationView开始。您可以使用它来使用predefined constants或float来为注释设置z-index。 同样,Apple使得我们最终可以自己为用户位置创建视图,并提供MKUserLocationView作为MKAnnotationView的子类。

From the documentation for MKUserLocationView

如果您要指定其他配置,例如zPriority, 直接创建此注释视图。要显示注释视图, 从mapView(_:viewFor:)返回实例。

以下代码段显示了如何完成此操作(将代码添加到您的MKMapViewDelegate):

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    
    // Alter the MKUserLocationView (iOS 14+)
    if #available(iOS 14.0, *), annotation is MKUserLocation {
        
        // Try to reuse the existing view that we create below
        let reuseIdentifier = "userLocation"
        if let existingView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) {
            return existingView
        }
        let view = MKUserLocationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        
        view.zPriority = .max   // Show user location above other annotations
        view.isEnabled = false  // Ignore touch events and do not show callout
        
        return view
    }
    
    // Create views for other annotations or return nil to use the default representation
    
    return nil
}

请注意,默认情况下,用户位置注释在点击时会显示一个标注。现在用户位置已经覆盖了其他注释,您可能需要禁用它,这可以通过将.isEnabled设置为false来在代码中完成。

答案 5 :(得分:1)

斯威夫特3:

internal func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
        for annotationView in views {
            if annotationView.annotation is MKUserLocation {
                annotationView.bringSubview(toFront: view)
                return
            }
            annotationView.sendSubview(toBack: view)
        }
 }

答案 6 :(得分:0)

以下是使用谓词执行此操作的方法。我认为它应该更快

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];
}

答案 7 :(得分:0)

使用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]]; });

答案 8 :(得分:0)

只需使用.layer.anchorPointZ属性。

示例:

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

这里有参考文献https://developer.apple.com/documentation/quartzcore/calayer/1410796-anchorpointz