自定义MKAnnotation标注视图?

con*_*ile 30 mapkit ios swift

我有一个MKPointAnnotation:

let ann = MKPointAnnotation()
self.ann.coordinate = annLoc
self.ann.title = "Customize me"
self.ann.subtitle = "???"
self.mapView.addAnnotation(ann)
Run Code Online (Sandbox Code Playgroud)

它看起来像这样:

在此输入图像描述

如何自定义此标注视图以创建我自己的视图而不是预定义的视图?

Rob*_*Rob 74

首先应该注意,通过简单地调整系统提供的标注的属性,但是自定义左右附件(通过rightCalloutAccessoryViewleftCalloutAccessoryView),可以对标注进行最简单的更改.您可以在中进行配置viewForAnnotation.

在iOS 9中,我们现在可以访问detailCalloutAccessoryView哪个,用可能视觉丰富的视图替换标注的副标题,同时仍然享受标注气泡的自动再现(使用自动布局使这更容易).

例如,这是一个标注,用于MKSnapshotter为细节标注附件中的图像视图提供图像,如WWDC 2015视频中所示.MapKit中的新功能:

在此输入图像描述

您可以通过以下方式实现此目的:

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation {
        return nil
    }

    let identifier = "MyCustomAnnotation"

    var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
    if annotationView == nil {
        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView?.canShowCallout = true
    } else {
        annotationView!.annotation = annotation
    }

    configureDetailView(annotationView!)

    return annotationView
}

func configureDetailView(annotationView: MKAnnotationView) {
    let width = 300
    let height = 200

    let snapshotView = UIView()
    let views = ["snapshotView": snapshotView]
    snapshotView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[snapshotView(300)]", options: [], metrics: nil, views: views))
    snapshotView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[snapshotView(200)]", options: [], metrics: nil, views: views))

    let options = MKMapSnapshotOptions()
    options.size = CGSize(width: width, height: height)
    options.mapType = .SatelliteFlyover
    options.camera = MKMapCamera(lookingAtCenterCoordinate: annotationView.annotation!.coordinate, fromDistance: 250, pitch: 65, heading: 0)

    let snapshotter = MKMapSnapshotter(options: options)
    snapshotter.startWithCompletionHandler { snapshot, error in
        if snapshot != nil {
            let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
            imageView.image = snapshot!.image
            snapshotView.addSubview(imageView)
        }
    }

    annotationView.detailCalloutAccessoryView = snapshotView
}
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找更激进的重新设计标注或需要支持9之前的iOS版本,则需要更多工作.该过程需要(a)禁用默认标注; (b)当用户点击现有注释视图(即地图上的视觉图钉)时添加您自己的视图.

然后是标注的设计复杂性,您必须绘制所需的所有内容.例如,如果你想绘制一个气泡以产生呼出的弹出感觉,你必须自己做.但是如果熟悉如何绘制形状,图像,文本等,您应该能够渲染一个能够实现所需UX的标注:

自定义标注

只需将视图添加为注释视图本身的子视图,并相应地调整其约束:

func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
    let calloutView = ...
    calloutView.translatesAutoresizingMaskIntoConstraints = false
    calloutView.backgroundColor = UIColor.lightGrayColor()
    view.addSubview(calloutView)

    NSLayoutConstraint.activateConstraints([
        calloutView.bottomAnchor.constraintEqualToAnchor(view.topAnchor, constant: 0),
        calloutView.widthAnchor.constraintEqualToConstant(60),
        calloutView.heightAnchor.constraintEqualToConstant(30),
        calloutView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor, constant: view.calloutOffset.x)
    ])
}
Run Code Online (Sandbox Code Playgroud)

有关创建自己的标注视图的示例,请参阅https://github.com/robertmryan/CustomMapViewAnnotationCalloutSwift.这只会添加两个标签,但它说明了您可以绘制任何所需形状的气泡,使用约束来指定标注的大小等.