自定义MKAnnotationView的弹出视图

43

我想创建一个自定义的MKAnnotationView弹出窗口,就像这张图片中显示的那样。我已经尝试过几种方案,但它们只允许自定义左/右图像和标题/副标题。有没有人能给我一些源代码或教程链接呢?

目前我一头雾水,请帮帮我。

这里输入图片描述


我认为这只是一个带有自定义图钉的自定义视图,你真正的问题是什么? - Mat
1
非常好的问题..这个也帮到了我..非常感谢Jennis.. - Mehul Mistri
示例演示 - http://stackoverflow.com/questions/27519517/button-action-in-mkannotation-view-not-working/27519673#27519673 - Kampai
3个回答

50
我理解您想要一个自定义标注弹出框。我们无法创建自定义标注弹出框,但是我们可以创建具有完全自定义视图的注释。因此,诀窍是在选择第一个注释时添加第二个注释,并使第二个注释视图看起来像一个标注气泡。
这是用户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“Annotation”对象。
#import <MapKit/MapKit.h>
@interface Content : NSObject
@property (nonatomic,assign) CLLocationCoordinate2D coordinate;
// ...

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

该注释实现了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初始化的,并包含核心图形代码(在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答案中包含了两个完整的项目,实现了这段代码(类名可能不同)。我还有另一个使用上述UML的项目,位于https://github.com/j4n0/callout


你好, 感谢你所做的出色工作。我正在尝试创建一个带有两个按钮的注释。 当我点击按钮时,我的CalloutView子类的handleTouch方法被调用。但是发送者是一个UITapGestureRecognizer,而不是我期望在sender.view中拥有我的按钮的注释视图?这是一个众所周知的问题吗?还是我做错了什么? - Thomas Besnehard
@amitgupta 提出具体问题。不要仅仅询问是否有人可以帮助你,而不详细描述你的问题。请参阅http://mattgemmell.com/what-have-you-tried/。 - Jano

1

我知道这个问题是来自2011年的,但是对于那些在搜索中仍然找到它的人: 在iOS 9中,你有MKAnnotationView.detailCalloutAccessoryView,它完全替代了标准的弹出框。


1
我在MKAnnotationView中添加了自定义的UIButton。当点击该按钮时,我显示了一个带有根视图控制器的popOver,其视图与您上面展示的视图类似。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接