自定义MKAnnotationView标注

时间:2011-11-05 07:39:05

标签: iphone ios ipad mkmapview mkannotationview

我想创建一个自定义的MKAnnotationView标注,如图所示。我已经测试了几种解决方案,但它们只允许自定义左/右图像和标题/副标题。有人可以给我一些源代码或教程链接吗?

目前我很无能为力。请帮忙。

enter image description here

3 个答案:

答案 0 :(得分:49)

我知道你想要一个带有自定义标注的针脚。

我们无法创建自定义标注,但我们可以使用完全自定义的视图创建注释。因此,诀窍是在选择第一个注释时添加第二个注释,并使第二个注释视图看起来像一个标注气泡。

这是用户djibouti33jacob-jennings在答案中发布的解决方案:MKAnnotationView - Lock custom annotation view to pin on location updates,后者又基于Asynchrony Solutions的blog post。出于解释目的,这里是一个分叉项目的一些UML: Annotation with custom XIB

这是一个很大的黑客,但也是我看到实现自定义注释的最干净的方法。

从NSObject“Content”类开始,该类有一个坐标,要使用的标注视图的类(在UML中是AnnotationView,但你可以在这里创建更多并设置它们),以及随机值的字典。标题,照片网址等。使用此类初始化MKAnnotation“注释”对象。

#import <MapKit/MapKit.h>
@interface Content : NSObject
@property (nonatomic,assign) CLLocationCoordinate2D coordinate;
// ...

@interface Annotation : NSObject <MKAnnotation, AnnotationProtocol>
-(id) initWithContent:(Content*)content;
// ...

Annotation实现了AnnotationProtocol,宣布它想要处理自己的MKAnnotationView的创建。也就是说,你的MKMapViewDelegate应该有这样的代码:

- (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id<MKAnnotation>)annotation 
{
    // if this is a custom annotation, delegate the implementation of the view
    if ([annotation conformsToProtocol:@protocol(AnnotationProtocol)]) {
        return [((NSObject<AnnotationProtocol>*)annotation) annotationViewInMap:mapView];
    } else {
        // else, return a standard annotation view
        // ...
    }
} 

返回的视图将是AnnotationView类型,它实现AnnotationViewProtocol以宣布它想要处理选择/取消选择。因此,在地图视图控制器中,方法mapView:didSelectAnnotationView:和mapView:didDeselectAnnotationView:应该以与我们之前看到的方式类似的方式进行委托。

当选择注释时,会添加第二个注释(CalloutAnnotation),它遵循相同的行为,但这次返回的视图(CalloutView)是从XIB初始化的,并包含Core Graphics代码(在BaseCalloutView中)以进行动画处理并复制一个标注。

CalloutView类的初始化程序:

- (id)initWithAnnotation:(CalloutAnnotation*)annotation
{
    NSString *identifier = NSStringFromClass([self class]);
    self = [super initWithAnnotation:annotation reuseIdentifier:identifier];
    if (self!=nil){
        [[NSBundle mainBundle] loadNibNamed:identifier owner:self options:nil];
        // prevent the tap and double tap from reaching views underneath
        UITapGestureRecognizer *tapGestureRecognizer = ...
    }
    return self;
}

为了能够从标注视图中推送另一个视图控制器,我使用了通知。

我在顶部链接的SO答案包含两个实现此代码的完整项目(类名可能不同)。我在https://github.com/j4n0/callout使用上面的UML有另一个项目。

答案 1 :(得分:0)

我在MKAnnotationView中添加了自定义UIButton。点击该按钮,我已经使用rootViewController显示了popOver,其视图与上面显示的类似。

答案 2 :(得分:0)

我知道这个问题来自2011年,但对于仍然在搜索中找到它的人: 在iOS 9中,您拥有MKAnnotationView.detailCalloutAccessoryView,它可以完全取代标准标注。