如何自定义MKAnnotation图钉的图片

问题描述 投票:0回答:1

我正在尝试更改

MKAnnotation
内的图像而不删除圆形形状。

这里我创建了一个自定义类

MKAnnotation

class MapPin: NSObject, MKAnnotation {
    let title: String?
    let locationName: String
    let coordinate: CLLocationCoordinate2D
    init(title: String, locationName: String, coordinate: CLLocationCoordinate2D) {
        self.title = title
        self.locationName = locationName
        self.coordinate = coordinate
    }
}

这里我创建了一个MapPin并将其添加到mapView

func setPinUsingMKAnnotation() {
   let pin1 = MapPin(title: "Here", locationName: "Device Location", coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
   let coordinateRegion = MKCoordinateRegion(center: pin1.coordinate, latitudinalMeters: 800, longitudinalMeters: 800)
   mapView.setRegion(coordinateRegion, animated: true)
   mapView.addAnnotations([pin1])
}

第一张图片是我创建的,第二张图片是我想要的。

enter image description here

我什至实现了

MKMapViewDelegate
:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    var annotationView = MKAnnotationView()
    annotationView.image = #imageLiteral(resourceName: "heart")
    return annotationView
}

这是结果:

enter image description here

圆形消失。

我看到很多关于如何自定义图钉的教程,但他们只解释了如何放置图像而不是图钉(如上面的壁炉图像)。我想知道如何更改图钉的图像(和颜色)并保持圆形形状(参见上面的蓝色图钉图像)。

有什么提示吗?谢谢

swift uikit mkmapview mkannotation mkannotationview
1个回答
9
投票

如果你想要圆形边框,你可以自己渲染它,或者更简单,子类

MKMarkerAnnotationView
而不是
MKAnnotationView

class CustomAnnotationView: MKMarkerAnnotationView {
    override var annotation: MKAnnotation? {
        didSet { configure(for: annotation) }
    }

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)

        configure(for: annotation)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func configure(for annotation: MKAnnotation?) {
        glyphImage = ...
        markerTintColor = ...
            
        displayPriority = .required

        // if doing clustering, also add
        // clusteringIdentifier = ...
    }
}

这样,您不仅可以获得圆形边框,还可以获得所有标记注释视图行为(显示标记下方注释视图的

title
,如果您在标记注释视图上选择,它会变大, ETC。)。如果没有必要,您可能不想从头开始编写许多标记注释视图行为。通过子类化
MKMarkerAnnotationView
而不是普通的
MKAnnotationView
,你可以免费获得所有这些行为。

例如,您可以:

class CustomAnnotationView: MKMarkerAnnotationView {
    static let glyphImage: UIImage = {
        let rect = CGRect(origin: .zero, size: CGSize(width: 40, height: 40))
        return UIGraphicsImageRenderer(bounds: rect).image { _ in
            let radius: CGFloat = 11
            let offset: CGFloat = 7
            let insetY: CGFloat = 5
            let center = CGPoint(x: rect.midX, y: rect.maxY - radius - insetY)
            let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: .pi, clockwise: true)
            path.addQuadCurve(to: CGPoint(x: rect.midX, y: rect.minY + insetY), controlPoint: CGPoint(x: rect.midX - radius, y: center.y - offset))
            path.addQuadCurve(to: CGPoint(x: rect.midX + radius, y: center.y), controlPoint: CGPoint(x: rect.midX + radius, y: center.y - offset))
            path.close()
            UIColor.white.setFill()
            path.fill()
        }
    }()

    override var annotation: MKAnnotation? {
        didSet { configure(for: annotation) }
    }

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)

        configure(for: annotation)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func configure(for annotation: MKAnnotation?) {
        glyphImage = Self.glyphImage
        markerTintColor = #colorLiteral(red: 0.005868499167, green: 0.5166643262, blue: 0.9889912009, alpha: 1)

        displayPriority = .required

        // if doing clustering, also add
        // clusteringIdentifier = ...
    }
}

结果:

enter image description here

显然,当你设置

glyphImage
时,将其设置为你想要的任何图像。旧的 SF Symbols 没有那个“drop”图像(尽管 iOS 14 有
drop.fill
)。但请提供您想要的任何 40 × 40 pt 图像视图。我自己渲染它,但您可以使用您想要的资产目录(或系统符号)中任何适当大小的图像。


顺便说一句,从 iOS 11 开始,你通常根本不会实现

mapView(_:viewFor:)
,除非绝对必要(在本例中并非如此)。例如,您可以摆脱
viewFor
方法,只需在
viewDidLoad
中注册自定义注释视图:

override func viewDidLoad() {
    super.viewDidLoad()

    mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.