首先应该注意的是,对标注的最简单的更改是通过简单地调整系统提供的标注的属性来实现的,但可以自定义右侧和左侧附件(通过rightCalloutAccessoryView
and leftCalloutAccessoryView
)。您可以在中进行该配置viewForAnnotation
.
从 iOS 9 开始,我们可以访问detailCalloutAccessoryView
其中,用可能视觉上丰富的视图替换标注的副标题,同时仍然享受标注气泡的自动呈现(使用自动布局使这更容易)。
例如,这是一个使用了MKSnapshotter
为详细标注附件中的图像视图提供图像,如 WWDC 2015 视频中所示MapKit 中的新功能 https://developer.apple.com/videos/play/wwdc2015-206/:
您可以通过以下方式实现此目的:
class SnapshotAnnotationView: MKPinAnnotationView {
override var annotation: MKAnnotation? { didSet { configureDetailView() } }
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
}
private extension SnapshotAnnotationView {
func configure() {
canShowCallout = true
configureDetailView()
}
func configureDetailView() {
guard let annotation = annotation else { return }
let rect = CGRect(origin: .zero, size: CGSize(width: 300, height: 200))
let snapshotView = UIView()
snapshotView.translatesAutoresizingMaskIntoConstraints = false
let options = MKMapSnapshotter.Options()
options.size = rect.size
options.mapType = .satelliteFlyover
options.camera = MKMapCamera(lookingAtCenter: annotation.coordinate, fromDistance: 250, pitch: 65, heading: 0)
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start { snapshot, error in
guard let snapshot = snapshot, error == nil else {
print(error ?? "Unknown error")
return
}
let imageView = UIImageView(frame: rect)
imageView.image = snapshot.image
snapshotView.addSubview(imageView)
}
detailCalloutAccessoryView = snapshotView
NSLayoutConstraint.activate([
snapshotView.widthAnchor.constraint(equalToConstant: rect.width),
snapshotView.heightAnchor.constraint(equalToConstant: rect.height)
])
}
}
当然,您可以将注释视图注册到您的地图上,并且不需要mapView(_:viewFor:)
根本需要:
mapView.register(SnapshotAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
如果您正在寻求对标注进行更彻底的重新设计,或者需要支持 9 之前的 iOS 版本,则需要做更多的工作。该过程需要 (a) 禁用默认标注; (b) 当用户点击现有注释视图(即地图上的视觉图钉)时添加您自己的视图。
然后,复杂性就出现在标注的设计中,您必须在其中绘制您想要可见的所有内容。例如。如果你想画一个气泡来产生呼出的弹出窗口的感觉,你必须自己做。但是,如果熟悉如何绘制形状、图像、文本等,您应该能够渲染实现所需用户体验的标注:
只需将视图添加为注释视图本身的子视图,并相应地调整其约束:
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
let calloutView = ...
calloutView.translatesAutoresizingMaskIntoConstraints = false
calloutView.backgroundColor = UIColor.lightGray
view.addSubview(calloutView)
NSLayoutConstraint.activate([
calloutView.bottomAnchor.constraint(equalTo: view.topAnchor, constant: 0),
calloutView.widthAnchor.constraint(equalToConstant: 60),
calloutView.heightAnchor.constraint(equalToConstant: 30),
calloutView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: view.calloutOffset.x)
])
}
See https://github.com/robertmryan/CustomMapViewAnnotationCalloutSwift https://github.com/robertmryan/CustomMapViewAnnotationCalloutSwift有关创建您自己的标注视图的示例。这仅添加了两个标签,但它说明了这样一个事实:您可以绘制气泡任何您想要的形状,使用约束来规定标注的大小等。