IOS - Swift高德地图自定义标注、气泡

高德地图官方文档:https://lbs.amap.com/api/ios-sdk/guide/draw-on-map/draw-marker

之前那些SDK导入就不做说明了,直接导入后,开始。

看高德地图官方文档基本都是OC语言写的,swift也就没这么详细说明了。

这种高度自定义,用的也是oc自定义,没有给出swift版本的demo出来,所以我们想做到后面这个效果来:

气泡在iOS中又称为callout,它由背景气泡内容构成,如下图所示:

也就是官方的效果。今天我们就用Swift来实现他了:

添加自定义气泡

(1) 新建自定义气泡类 CustomCalloutViewSwift,继承 UIView。

(2)在类中重写UIView的drawRect方法,绘制弹出气泡的背景,可以自己更改背景颜色。 

(3)定义用于显示气泡内容的控件,并添加到SubView中。如上图所示气泡,我们需要一个UIImageView和两个UILabel

(4)在CustomCalloutView.m中给控件传入数据。

扫描二维码关注公众号,回复: 11702734 查看本文章
import UIKit

class CustomCalloutViewSwift: UIView{
    var portraitView : UIImageView!
    var subtitleLabel : UILabel!
    var titleLabel : UILabel!
    
    //初始化定义气泡的背景
    override func draw(_ rect: CGRect) {
        drawInContext(context: UIGraphicsGetCurrentContext()!)
        self.layer.shadowColor = UIColor.red.cgColor
        self.layer.shadowOpacity = 1.0
        self.layer.shadowOffset = CGSize.init(width: 0.0, height: 0.0)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
//        self.backgroundColor = UIColor.red
        
        initSubViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initSubViews()
        fatalError("init(coder:) has not been implemented")
    }
    
    func drawInContext(context : CGContext) {
        context.setLineWidth(2.0)
        context.setFillColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 0.8)
        getDrawPath(context: context)
        context.fillPath()
    }
    
    func getDrawPath(context : CGContext) {
        let kArrorHeight = 10
        let rect = self.bounds
        let radius = 6.0
        let minx = rect.minX
        let midx = rect.midX
        let maxx = rect.maxX
        let miny = rect.minY
        let maxy = rect.maxY - 10
        
        context.move(to: CGPoint.init(x: midx + CGFloat(kArrorHeight), y: maxy))
        context.addLine(to: CGPoint.init(x: midx, y: maxy + CGFloat(kArrorHeight)))
        context.addLine(to: CGPoint.init(x: midx - CGFloat(kArrorHeight), y: maxy))
        
        context.addArc(tangent1End: CGPoint.init(x: minx, y: maxy), tangent2End: CGPoint.init(x: minx, y: miny), radius: CGFloat(radius))
        context.addArc(tangent1End: CGPoint.init(x: minx, y: minx), tangent2End: CGPoint.init(x: maxx, y: miny), radius: CGFloat(radius))
        context.addArc(tangent1End: CGPoint.init(x: maxx, y: miny), tangent2End: CGPoint.init(x: maxx, y: maxx), radius: CGFloat(radius))
        context.addArc(tangent1End: CGPoint.init(x: maxx, y: maxy), tangent2End: CGPoint.init(x: midx, y: maxy), radius: CGFloat(radius))
        context.closePath();
    }
    
    //初始化定义气泡的内容
    func initSubViews() {
        backgroundColor = UIColor.clear
        let kPortraitMargin = 5.0
        let kPortraitWidth = 70.0
        let kPortraitHeight = 50.0
        let kTitleWidth = 120.0
        let kTitleHeight = 20.0
        
        // 添加图片,即商户图
        portraitView = UIImageView.init(frame: CGRect.init(x: kPortraitMargin, y: kPortraitMargin, width: kPortraitWidth, height: kPortraitHeight))
        portraitView.backgroundColor = UIColor.black
        addSubview(portraitView)
        
        // 添加标题,即商户名
        titleLabel = UILabel.init(frame: CGRect.init(x: kPortraitMargin * 2 + kPortraitWidth, y: kPortraitMargin, width: kTitleWidth, height: kTitleHeight))
        titleLabel.font = UIFont.systemFont(ofSize: 14)
        titleLabel.textColor = UIColor.white
        titleLabel.text = "我是商户名"
        addSubview(titleLabel)
        
        // 添加副标题,即商户地址
        subtitleLabel = UILabel.init(frame: CGRect.init(x: kPortraitMargin * 2 + kPortraitWidth, y: kPortraitMargin * 2 + kTitleHeight, width: kTitleWidth, height: kTitleHeight))
        subtitleLabel.font = UIFont.systemFont(ofSize: 12)
        subtitleLabel.textColor = UIColor.lightGray
        subtitleLabel.text = "我是商户地址"
        addSubview(subtitleLabel)
    }
    
    //给控件传入数据
    func setTitle(title : NSString) {
        titleLabel.text = title as String;
    }
    
    func setSubtitle(subtitle : NSString) {
        subtitleLabel.text = subtitle as String;
    }
    
    func setImage(image : UIImage) {
        portraitView.image = image;
    }
    
    ///导航事件
    @objc func guidBtnAction() {
//        self.guideActionCallBack?()
    }
    
    func guideActionCallBack() {
        print("click btn")
    }
}

以上就是自定义气泡的全部过程,但是为了在点击标注时,弹出自定义的气泡,还需要。步骤如下:

添加自定义AnnotationView

(1) 新建类CustomAnnotationViewSwift,继承MAAnnotationView或MAPinAnnotationView。若继承MAAnnotationView,则需要设置标注图标;若继承MAPinAnnotationView,使用默认的大头针标注

(2) 在CustomAnnotationViewSwift中定义自定义气泡属性,可修改calloutView属性

(3) 重写选中方法setSelected。选中时新建并添加calloutView,传入数据;非选中时删除calloutView。

import UIKit

class CustomAnnotationViewSwift: MAAnnotationView {
    //定义气泡背景与内容对象
    var calloutView : CustomCalloutViewSwift?
    
    var content : String?
    
    //重写选中效果
    override func setSelected(_ selected: Bool, animated: Bool) {
        if self.isSelected == selected{
            return;
        }
        if selected {
            if calloutView == nil {
                calloutView = CustomCalloutViewSwift.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 70))
                calloutView!.center = CGPoint.init(x: bounds.width/2 + calloutOffset.x, y: -calloutView!.bounds.height/2 + calloutOffset.y)
            }
            
            //传入数据给气泡内容
            let image = UIImage.init(named: "MyImageName")
            calloutView?.setImage(image: image!)

            calloutView?.setTitle(title: "我是商家名")
            calloutView?.setSubtitle(subtitle: "我是商家地址")

            addSubview(calloutView!)
        } else {
            calloutView!.removeFromSuperview()
        }
        super.setSelected(selected, animated: animated)
    }
    
    func setContent(content : String){
        self.content = content
    }
}

定义了上面两个类,我们直接在地图上调用就好了,

 func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {
//MAPointAnnotation,自定义POI点数据,参考demo河马
        if annotation is MAPointAnnotation {
            let customReuseIndetifier: String = "customReuseIndetifier"
            //从复用内存池中获取制定复用标识的annotation view,自定义气泡样式CustomAnnotationView
//            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: customReuseIndetifier) as? CustomAnnotationView
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: customReuseIndetifier) as? CustomAnnotationViewSwift
            if annotationView == nil {
                annotationView = CustomAnnotationViewSwift.init(annotation: annotation, reuseIdentifier: customReuseIndetifier)

                //是否允许弹出callout
                annotationView?.canShowCallout = false
                ///添加到地图时是否使用下落动画效果
                //            annotationView!.animatesDrop = false
                ///是否支持拖动
                annotationView?.isDraggable = true
                ///弹出框默认位于view正中上方,可以设置calloutOffset改变view的位置,正的偏移使view朝右下方移动,负的朝左上方,单位是屏幕坐标
                annotationView?.calloutOffset = CGPoint.init(x: 0, y: -5)
            }
            
            let wellBlueState = UIImage(named: "restaurant")
            annotationView?.image = wellBlueState
            //背景颜色,透明
            annotationView?.backgroundColor = Theme.transparent
            annotationView?.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
//            annotationView?.portrait = UIImage.init(named: "login")
//            annotationView?.name = "河马"
            
            
            return annotationView
        }

        return nil
    }

自定义调用:var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: customReuseIndetifier) as? CustomAnnotationViewSwift

运行程序,效果如下:

猜你喜欢

转载自blog.csdn.net/qq_31622345/article/details/100772687
今日推荐