| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- //
- // MapAnnotationView.swift
- // Runner
- //
- // Created by Groot on 2025/5/9.
- //
- import UIKit
- import MapKit
- class MapAnnotationView: MKAnnotationView {
-
- static let identifier: String = "MapAnnotationView"
- var marker: ATMapMarker? {
- didSet {
- updateView()
- }
- }
- var markerImageView: MapAnnotationMarkerImageView?
- var textView: MapAnnotationMarkerTextView?
-
- // spacing between text and image
- let spacing: CGFloat = 6
-
- var annotationSelected: Bool {
- return (marker?.isSelected ?? false) || self.isSelected
- }
-
- override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
- super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
- self.marker = annotation as? ATMapMarker
- self.isEnabled = marker?.markerType.supportSelected ?? false
- self.isHidden = false
- }
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - 视图更新与重用
-
- override func prepareForReuse() {
- super.prepareForReuse()
- // 清除当前所有子视图
- for subview in subviews {
- subview.removeFromSuperview()
- }
- markerImageView = nil
- textView = nil
- }
-
- private func updateView() {
- // 确保在更新视图前移除所有子视图
- for subview in subviews {
- subview.removeFromSuperview()
- }
-
- guard let marker = marker else { return }
-
- // 创建并添加图像视图
- markerImageView = MapAnnotationMarkerImageView(markerType: marker.markerType)
- if let url = marker.customAvatarUrl, !url.isEmpty {
- markerImageView?.loadNetworkImage(imageUrl: url)
- }
- if let markerImageView = markerImageView {
- markerImageView.isSelected = annotationSelected
- addSubview(markerImageView)
- }
-
- // 如果有标题,添加文本视图
- if let markerName = marker.markerName, !markerName.isEmpty {
- textView = MapAnnotationMarkerTextView(text: markerName)
- if let textView = textView {
- addSubview(textView)
- }
- }
-
- // 设置AutoLayout
- setupConstraints()
- }
-
- // MARK: - 布局
-
- private func setupConstraints() {
- // 禁用自动约束转换
- translatesAutoresizingMaskIntoConstraints = false
-
- guard let markerImageView = markerImageView else { return }
- markerImageView.translatesAutoresizingMaskIntoConstraints = false
-
- var markerSize = marker?.markerType.size ?? CGSize(width: 30, height: 30)
- if let url = marker?.customAvatarUrl, !url.isEmpty {
- markerSize = CGSize(width: 52, height: 52)
- markerImageView.layer.cornerRadius = 52 / 2
- markerImageView.layer.masksToBounds = true // 确保超出部分被裁剪
- }
-
- // 设置图像视图约束 - 居中显示在标记视图中
- NSLayoutConstraint.activate([
- markerImageView.centerXAnchor.constraint(equalTo: centerXAnchor),
- markerImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
- markerImageView.widthAnchor.constraint(equalToConstant: markerSize.width),
- markerImageView.heightAnchor.constraint(equalToConstant: markerSize.height)
- ])
-
- // 设置文本视图约束 - 位于图像上方,居中对齐
- if let textView = textView {
- textView.translatesAutoresizingMaskIntoConstraints = false
- NSLayoutConstraint.activate([
- textView.centerXAnchor.constraint(equalTo: centerXAnchor),
- textView.bottomAnchor.constraint(equalTo: markerImageView.topAnchor, constant: -spacing)
- ])
- }
-
- // 设置标记视图整体尺寸
- let textHeight = textView?.intrinsicContentSize.height ?? 0
- let totalHeight = textView != nil ?
- markerSize.height + textHeight + spacing :
- markerSize.height
-
- // 宽度至少和markerImageView一样宽,高度根据是否有文本决定
- NSLayoutConstraint.activate([
- widthAnchor.constraint(greaterThanOrEqualTo: markerImageView.widthAnchor),
- heightAnchor.constraint(equalToConstant: totalHeight)
- ])
-
- // 更新偏移量
- updateCenterOffset()
- }
-
- // MARK: - 更新视图
-
- override func layoutSubviews() {
- super.layoutSubviews()
- updateCenterOffset()
- }
-
- private func updateCenterOffset() {
- let markerSize = marker?.markerType.size ?? CGSize(width: 30, height: 30)
-
- if let textView = textView {
- let textHeight = textView.frame.height
- let totalHeight = markerSize.height + textHeight + spacing
-
- // 有文本时,调整偏移让图片底部对准坐标点
- centerOffset = CGPoint(x: 0, y: -(totalHeight - markerSize.height)/2)
- } else {
- // 没有文本时,仅需要将图片底部对准坐标点
- centerOffset = CGPoint(x: 0, y: -markerSize.height/2)
- }
- }
-
- override func prepareForDisplay() {
- super.prepareForDisplay()
- // 确保视图已经设置好
- if markerImageView == nil {
- updateView()
- }
- // 更新选中状态
- markerImageView?.isSelected = annotationSelected
- }
- override func setSelected(_ selected: Bool, animated: Bool) {
- super.setSelected(selected, animated: animated)
- marker?.isSelected = selected
- markerImageView?.isSelected = annotationSelected
- }
- }
|