MapAnnotationView.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //
  2. // MapAnnotationView.swift
  3. // Runner
  4. //
  5. // Created by Groot on 2025/5/9.
  6. //
  7. import UIKit
  8. import MapKit
  9. class MapAnnotationView: MKAnnotationView {
  10. static let identifier: String = "MapAnnotationView"
  11. var marker: ATMapMarker?
  12. var markerImageView: MapAnnotationMarkerImageView!
  13. var textView: MapAnnotationMarkerTextView?
  14. // spacing between text and image
  15. let spacing: CGFloat = 6
  16. var annotationSelected: Bool {
  17. return (marker?.isSelected ?? false) || self.isSelected
  18. }
  19. override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
  20. self.marker = annotation as? ATMapMarker
  21. super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
  22. self.isEnabled = marker?.markerType.supportSelected ?? false
  23. self.isHidden = false
  24. setupViews()
  25. }
  26. required init?(coder aDecoder: NSCoder) {
  27. fatalError("init(coder:) has not been implemented")
  28. }
  29. // MARK: - 设置视图
  30. private func setupViews() {
  31. // 创建并添加图像视图
  32. markerImageView = MapAnnotationMarkerImageView(markerType: marker?.markerType ?? MarkerType.mine)
  33. markerImageView.isSelected = annotationSelected
  34. addSubview(markerImageView)
  35. // 如果有标题,添加文本视图
  36. if let markerName = marker?.markerName, !markerName.isEmpty {
  37. textView = MapAnnotationMarkerTextView(text: markerName)
  38. if let textView = textView {
  39. addSubview(textView)
  40. }
  41. }
  42. // 设置AutoLayout
  43. setupConstraints()
  44. }
  45. // MARK: - 布局
  46. private func setupConstraints() {
  47. // 禁用自动约束转换
  48. translatesAutoresizingMaskIntoConstraints = false
  49. markerImageView.translatesAutoresizingMaskIntoConstraints = false
  50. let markerSize = marker?.markerType.size ?? CGSize(width: 30, height: 30)
  51. // 设置图像视图约束 - 居中显示在标记视图中
  52. NSLayoutConstraint.activate([
  53. markerImageView.centerXAnchor.constraint(equalTo: centerXAnchor),
  54. markerImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
  55. markerImageView.widthAnchor.constraint(equalToConstant: markerSize.width),
  56. markerImageView.heightAnchor.constraint(equalToConstant: markerSize.height)
  57. ])
  58. // 设置文本视图约束 - 位于图像上方,居中对齐
  59. if let textView = textView {
  60. textView.translatesAutoresizingMaskIntoConstraints = false
  61. NSLayoutConstraint.activate([
  62. textView.centerXAnchor.constraint(equalTo: centerXAnchor),
  63. textView.bottomAnchor.constraint(equalTo: markerImageView.topAnchor, constant: -spacing)
  64. ])
  65. }
  66. // 设置标记视图整体尺寸
  67. let textHeight = textView?.intrinsicContentSize.height ?? 0
  68. let totalHeight = textView != nil ?
  69. markerSize.height + textHeight + spacing :
  70. markerSize.height
  71. // 宽度至少和markerImageView一样宽,高度根据是否有文本决定
  72. NSLayoutConstraint.activate([
  73. widthAnchor.constraint(greaterThanOrEqualTo: markerImageView.widthAnchor),
  74. heightAnchor.constraint(equalToConstant: totalHeight)
  75. ])
  76. // 更新偏移量
  77. updateCenterOffset()
  78. }
  79. // MARK: - 更新视图
  80. override func layoutSubviews() {
  81. super.layoutSubviews()
  82. updateCenterOffset()
  83. }
  84. private func updateCenterOffset() {
  85. let markerSize = marker?.markerType.size ?? CGSize(width: 30, height: 30)
  86. if let textView = textView {
  87. let textHeight = textView.frame.height
  88. let totalHeight = markerSize.height + textHeight + spacing
  89. // 有文本时,调整偏移让图片底部对准坐标点
  90. centerOffset = CGPoint(x: 0, y: -(totalHeight - markerSize.height)/2)
  91. } else {
  92. // 没有文本时,仅需要将图片底部对准坐标点
  93. centerOffset = CGPoint(x: 0, y: -markerSize.height/2)
  94. }
  95. }
  96. override func prepareForDisplay() {
  97. super.prepareForDisplay()
  98. updateImage()
  99. }
  100. private func updateImage() {
  101. markerImageView.isSelected = annotationSelected
  102. }
  103. override func setSelected(_ selected: Bool, animated: Bool) {
  104. super.setSelected(selected, animated: animated)
  105. marker?.isSelected = selected
  106. updateImage()
  107. }
  108. }