标签:
2:使用图片显示大头针视图,并使用自定义大头针模型、
3:自定义弹出视图、
4:适用于顶部title,底部自定义视图 ios9之后
代码部分:
class SecondViewController: UIViewController { lazy var mapView: MKMapView = { let mapView = MKMapView(frame: UIScreen.mainScreen().bounds) mapView.mapType = .Standard mapView.scrollEnabled = true mapView.zoomEnabled = true mapView.showsUserLocation = true mapView.delegate = self return mapView }() override func viewDidLoad() { super.viewDidLoad() view.addSubview(self.mapView) addAnnotations() } //MARK: 添加大头针 func addAnnotations(){ //创建MKPointAnnotation对象 let pointAnnotation = MKPointAnnotation() pointAnnotation.coordinate = CLLocationCoordinate2DMake(39, 100) pointAnnotation.title = "Jack" pointAnnotation.subtitle = "hua" self.mapView.addAnnotation(pointAnnotation) //创建自定义大头针并添加到地图上 let annotationOne = FirstAnnotation(coordinate: CLLocationCoordinate2DMake(39, 115),title:"xxx大饭店",subtitle:"全场一律15折,会员20折") annotationOne.iconImage = UIImage(named: "boy") self.mapView.addAnnotation(annotationOne) //自定义弹出视图 let calloutAnnotation = <span style="font-family: Menlo; font-variant-ligatures: no-common-ligatures;">SecondAnnotation</span><span style="font-family: 'PingFang SC';">(coordinate: CLLocationCoordinate2DMake(39, 80))</span> calloutAnnotation.icon = UIImage(named: "icon_classify_cafe") calloutAnnotation.rate = UIImage(named: "icon_Movie_Star_rating") calloutAnnotation.descriptionDetail = "This is a nice restaurant!I'm sure you will enjoy here!Come to here,everone!" self.mapView.addAnnotation(calloutAnnotation) //使用系统自带附属视图 let detailAnnotation = DetailCalloutAccessoryAnnotation(coordinate: CLLocationCoordinate2DMake(39, 90),title:"Jack") self.mapView.addAnnotation(detailAnnotation) } }
代码分析:
上面代码主要是将地图添加到当前视图控制器视图上,并添加4个大头针到地图上,自定义大头针模型对象代码如下:
//自定义大头针模型 class FirstAnnotation: NSObject,MKAnnotation { //位置 var coordinate: CLLocationCoordinate2D //主标题 var title: String? //副标题 var subtitle: String? //图片icon var iconImage: UIImage? init(coordinate: CLLocationCoordinate2D,title: String,subtitle:String) { self.coordinate = coordinate self.title = title self.subtitle = subtitle super.init() } } //用于弹出框类型判断模型 class SecondAnnotation: NSObject,MKAnnotation { //位置 var coordinate: CLLocationCoordinate2D //左侧icon var icon: UIImage? //icon描述 var descriptionDetail: String? //底部评分视图 var rate: UIImage? init(coordinate: CLLocationCoordinate2D) { self.coordinate = coordinate super.init() } } //弹出视图模型 class SHCalloutAnnotation: NSObject,MKAnnotation{ var coordinate: CLLocationCoordinate2D init(coordinate: CLLocationCoordinate2D) { self.coordinate = coordinate super.init() } //左侧icon var icon: UIImage? //icon描述 var descriptionDetail: String? //底部评分视图 var rate: UIImage? } //附属视图模型 class DetailCalloutAccessoryAnnotation: NSObject,MKAnnotation { //位置 var coordinate: CLLocationCoordinate2D //主标题 var title: String? //副标题 var subtitle: String? init(coordinate: CLLocationCoordinate2D,title: String) { self.coordinate = coordinate self.title = title super.init() } //官方示例代码使用:在模型中创建大头针视图 class func createViewAnnotationForMapView(mapView:MKMapView, annotation:MKAnnotation) ->MKAnnotationView{ let identifier = "DetailCalloutAccessoryAnnotation" var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView if (annotationView == nil){ annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) annotationView!.canShowCallout = true //设置大头针颜色 annotationView!.pinColor = MKPinAnnotationColor.Purple let backgroundView = UIView(frame: CGRectZero) backgroundView.backgroundColor = UIColor.redColor() //添加约束才可以使用自定义视图 let widthConstraint = NSLayoutConstraint(item: backgroundView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 200) backgroundView.addConstraint(widthConstraint) let heightConstraint = NSLayoutConstraint(item: backgroundView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 200) backgroundView.addConstraint(heightConstraint) if #available(iOS 9.0, *) { //赋值UIImageView直接可以使用 //returnAnnotaionView!.detailCalloutAccessoryView = UIImageView(image: UIImage(named: "icon_classify_cafe")) //直接赋值UIView,UILabel等视图不行?http://stackoverflow.com/questions/32581049/mapkit-ios-9-detailcalloutaccessoryview-usage 因为我们需要对宽和高做约束 annotationView!.detailCalloutAccessoryView = backgroundView } else { print("iOS9以下系统暂时不能够使用!") } } return annotationView! } }
接下来,继续看一下视图控制器中的代码,我通过extension实现协议内容:
extension SecondViewController:MKMapViewDelegate{ //显示大头针时调用,注意方法中的annotation参数是即将显示的大头针对象.1)该方法首先显示大头针的时候会调用2)向地图上添加大头针的时候也会调用 func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { var returnAnnotaionView:MKAnnotationView? if !(annotation.isKindOfClass(MKUserLocation)){//根据模型进行分类 if annotation.isKindOfClass(MKPointAnnotation.self){ //MARK:使用系统样式大头针视图和系统大头针模型 let identifier = "MKPinAnnotationView" var returnAnnotaionView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) if (returnAnnotaionView == nil){ returnAnnotaionView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) returnAnnotaionView!.canShowCallout = true returnAnnotaionView!.calloutOffset = CGPoint(x: 0, y: -10) returnAnnotaionView!.leftCalloutAccessoryView = UIButton(type: .ContactAdd) returnAnnotaionView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure) }else{ returnAnnotaionView!.annotation = annotation } return returnAnnotaionView }else if annotation.isKindOfClass(FirstAnnotation.self){ //MARK:使用图片显示大头针视图,并使用自定义大头针模型 returnAnnotaionView = SHAnnotationView.annotationViewWith(mapView, reuseIdentifier:"SHAnnotationView") returnAnnotaionView!.annotation = annotation return returnAnnotaionView }else if annotation.isKindOfClass(SecondAnnotation.self){ let identifier = "Annotation" var returnAnnotaionView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView if (returnAnnotaionView == nil){ returnAnnotaionView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) returnAnnotaionView!.pinColor = MKPinAnnotationColor.Green } returnAnnotaionView!.annotation = annotation return returnAnnotaionView }else if annotation.isKindOfClass(SHCalloutAnnotation.self){ //MARK:自定义弹出视图 returnAnnotaionView = SHCalloutAnnotationView.calloutAnnotationViewWith(mapView) returnAnnotaionView!.annotation = annotation return returnAnnotaionView }else if annotation.isKindOfClass(DetailCalloutAccessoryAnnotation.self){ //MARK:适用于顶部title,底部自定义视图 ios9之后 returnAnnotaionView = DetailCalloutAccessoryAnnotation.createViewAnnotationForMapView(mapView, annotation: annotation) returnAnnotaionView!.annotation = annotation return returnAnnotaionView } } return returnAnnotaionView } //选中大头针时触发 func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) { //点击大头针模型为SecondAnnotation时,添加自定义弹出视图的大头针到地图上。 if let annotation = view.annotation{ if(annotation.isKindOfClass(SecondAnnotation.self)){ let annotation = annotation as! SecondAnnotation let calloutAnnotaion = SHCalloutAnnotation(coordinate: annotation.coordinate) calloutAnnotaion.icon = annotation.icon calloutAnnotaion.rate = annotation.rate calloutAnnotaion.descriptionDetail = annotation.descriptionDetail mapView.addAnnotation(calloutAnnotaion) } } } //反选时触发 func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) { for annotation in self.mapView.annotations { if annotation.isKindOfClass(SHCalloutAnnotation.self){ dispatch_async(dispatch_get_main_queue(), { mapView.removeAnnotation(annotation) }) } } } }
以及自定义视图部分:
//边距 public let CalloutBorderSpace:CGFloat = 5 //MARK:自定义大头针视图 class SHAnnotationView: MKAnnotationView { class func annotationViewWith(mapView: MKMapView,reuseIdentifier:String) ->SHAnnotationView{ //从缓存池中取出可以循环利用的大头针view var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier) as? SHAnnotationView if annotationView == nil{ annotationView = SHAnnotationView(annotation: nil, reuseIdentifier:reuseIdentifier) annotationView?.canShowCallout = true annotationView?.leftCalloutAccessoryView = UIButton(type: .InfoDark) annotationView?.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure) } return annotationView! } override var annotation: MKAnnotation?{ didSet(annotation){ //显示大头针为图片 if let annotationOne = annotation as? FirstAnnotation{ self.image = annotationOne.iconImage } } } } //MARK:弹出视图 继承于MKAnnotationView进行显示视图 class SHCalloutAnnotationView: MKAnnotationView{ //#MARK:使用懒加载声明需要的控件属性 lazy var leftIcon:UIImageView = { let leftIcon = UIImageView() self.addSubview(leftIcon) return leftIcon }() lazy var detailLabel:UILabel = { let detailLabel = UILabel(frame: CGRectZero) detailLabel.lineBreakMode = .ByCharWrapping detailLabel.font = UIFont.systemFontOfSize(12) detailLabel.numberOfLines = 0 self.addSubview(detailLabel) return detailLabel }() lazy var rateIcon:UIImageView = { let rateIcon = UIImageView() self.addSubview(rateIcon) return rateIcon }() var button:UIButton! //#MARK: 创建弹出视图 class func calloutAnnotationViewWith(mapView: MKMapView)-> SHCalloutAnnotationView{ let indentifier = "SHCallOutAnnotationView" var calloutView = mapView.dequeueReusableAnnotationViewWithIdentifier(indentifier) as? SHCalloutAnnotationView if calloutView == nil{ calloutView = SHCalloutAnnotationView() calloutView!.backgroundColor = UIColor.grayColor() } return calloutView! } //#MARK:赋值数据模型显示相应的数据 override var annotation: MKAnnotation?{ didSet(callOutAnnotation){ if let callOutAnnotation = callOutAnnotation as? SHCalloutAnnotation{ self.leftIcon.image = callOutAnnotation.icon self.leftIcon.frame = CGRect(x: CalloutBorderSpace, y: CalloutBorderSpace, width: callOutAnnotation.icon!.size.width, height: callOutAnnotation.icon!.size.height) self.detailLabel.text = callOutAnnotation.descriptionDetail let string:NSString = self.detailLabel.text! let detailLabelSize = string.boundingRectWithSize(CGSize(width: 200,height: 200), options:.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: self.detailLabel.font], context: nil) self.detailLabel.frame = CGRect(x: CGRectGetMaxX(self.leftIcon.frame) + CalloutBorderSpace, y:CGRectGetMinY(self.leftIcon.frame), width: detailLabelSize.width, height: detailLabelSize.height) self.rateIcon.image = callOutAnnotation.rate self.rateIcon.frame = CGRect(x: CGRectGetMinX(self.detailLabel.frame), y: CGRectGetMaxY(self.detailLabel.frame) + CalloutBorderSpace, width: callOutAnnotation.rate!.size.width, height: callOutAnnotation.rate!.size.height) self.bounds = CGRect(x: 0, y: 0, width: CGRectGetMaxX(self.detailLabel.frame) + CalloutBorderSpace, height: CGRectGetMaxY(self.rateIcon.frame) + CalloutBorderSpace) //注意:确定最终的显示位置 self.centerOffset = CGPointMake(0, -self.bounds.size.height) } } } //#MARK:当弹出视图显示的时候添加缩放动画 override func didMoveToSuperview() { let animation = CAKeyframeAnimation(keyPath: "transform.scale") animation.values = [0,1.5,1,1.5,1] animation.duration = 0.5 self.layer.addAnimation(animation, forKey: nil) } }
代码分析:
我们之前已经添加了4个大头针到地图,当显示大头针的时候,会触发mapView(mapView:MKMapView, viewForAnnotation annotation:MKAnnotation)方法获取大头针视图,我们根据所添加的大头针模型进行分类返回对应的大头针视图。
对于显示使用系统样式大头针视图和系统大头针模型、使用图片显示大头针视图,并使用自定义大头针模型、ios9之后出现的附属视图的属性等都很简单,直接看代码就好。主要分析一下是如何实现callout视图的:
首先是添加一个大头针到视图上,当该大头针被点击的时候,添加我们自定义的大头针SecondAnnotation对象,所有数据都是源于原大头针模型,然后会触发mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation)方法,进行添加我们自定义的callout视图。并赋值annotation数据,显示整个视图。
实现效果图如下:
MapKit之大头针全面解析(使用系统大头针、自定义大头针callout视图、使用图片显示大头针)
标签:
原文地址:http://blog.csdn.net/longshihua/article/details/51720677