| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- //
- // MapAmapPopUpWindowView.swift
- // map_amap_ios
- //
- // Created by 诺诺诺的言 on 2025/7/22.
- //
- import Foundation
- //import MapKit
- import MAMapKit
- class MapAmapPopUpWindowView : MAPinAnnotationView {
-
- static let identifier: String = "MapAnotationBubbleView"
- var marker: ATMapMarker? {
- didSet {
- updateView()
- }
- }
-
- private var allContentView : UIView!
- private var markerContentView : UIView!
- private var bgImageView : UIImageView!
-
- private var titleLabelView: UILabel!
- private var bottomView : UIView!
- private var triangleLayer: CAShapeLayer!
-
- private var bubbleHeight: CGFloat = 24
- private var triangleHeight: CGFloat = 6
-
- // spacing between text and image
- let spacing: CGFloat = 6
-
- var annotationSelected: Bool {
- return (marker?.isSelected ?? false) || self.isSelected
- }
-
- override init!(annotation: (any MAAnnotation)!, reuseIdentifier: String!) {
- super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
- self.marker = annotation as? ATMapMarker
- self.isEnabled = marker?.markerType.supportSelected ?? false
- self.isHidden = false
- }
-
- /*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()
- }
- markerContentView = nil
- markerContentView = nil
- }
-
- private func updateView() {
- // 确保在更新视图前移除所有子视图
- for subview in subviews {
- subview.removeFromSuperview()
- }
-
- guard let marker = marker else { return }
-
- let tags = marker.tags
- let mainTiel : String = tags?["title"] ?? "";
- let mainDesc : String = tags?["desc"] ?? "";
-
- let markerContentViewW = 170
-
- markerContentView = UIView()
- markerContentView.backgroundColor = UIColor(hex: "#FFFFFF")
- markerContentView.layer.cornerRadius = 12
- markerContentView.layer.masksToBounds = true
- markerContentView.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.08).cgColor
- markerContentView.layer.shadowOpacity = 1
- markerContentView.layer.shadowRadius = 4
- markerContentView.layer.shadowOffset = CGSize(width: 0, height: 4)
- addSubview(markerContentView)
-
-
- titleLabelView = UILabel()
- titleLabelView.translatesAutoresizingMaskIntoConstraints = false // 关键
- titleLabelView.text = mainTiel
- titleLabelView.font = UIFont.systemFont(ofSize: 10, weight: .bold)
- titleLabelView.textColor = UIColor(hex: "#333333")
- titleLabelView.backgroundColor = .clear
- titleLabelView.textAlignment = .left
- titleLabelView.numberOfLines = 0
- markerContentView.addSubview(titleLabelView)
-
- bottomView = UIView()
- bottomView.translatesAutoresizingMaskIntoConstraints = false // 关键
- markerContentView.addSubview(bottomView)
-
- let mapIconView = UIImageView(frame: CGRect(x: 0, y: 0, width: 12, height: 12))
- mapIconView.image = readImageContentFrom(imageName: "com.shishi.dingwei_map_pin.png")
- mapIconView.contentMode = .scaleAspectFit
- bottomView.addSubview(mapIconView)
-
-
- let mapLableW = markerContentViewW - 16 - 14
- let mapLable = UILabel(frame: CGRect(x: 14, y: 0, width: mapLableW, height: 14))
- mapLable.text = mainDesc
- mapLable.font = UIFont.systemFont(ofSize: 10, weight: .regular)
- mapLable.textColor = UIColor(hex: "#666666")
- mapLable.backgroundColor = .clear
- mapLable.textAlignment = .left
- mapLable.lineBreakMode = .byTruncatingTail
- mapLable.numberOfLines = 1 // 限制为单行
- bottomView.addSubview(mapLable)
-
-
- // 创建气泡三角形
- triangleLayer = CAShapeLayer()
- triangleLayer.fillColor = UIColor.white.cgColor
-
- let trianglePath = UIBezierPath()
- trianglePath.move(to: CGPoint(x: 0, y: 0)) // 左点
- trianglePath.addLine(to: CGPoint(x: 5, y: 6)) // 底点
- trianglePath.addLine(to: CGPoint(x: 10, y: 0)) // 右点
- trianglePath.close()
-
- triangleLayer.path = trianglePath.cgPath
- layer.addSublayer(triangleLayer)
-
- // 设置AutoLayout
- setupConstraints()
- }
-
- // MARK: - 布局
-
- private func setupConstraints() {
- // 禁用自动约束转换
- translatesAutoresizingMaskIntoConstraints = false
-
-
- guard let marker = marker else { return }
-
- let tags = marker.tags
- let mainTiel : String = tags?["title"] ?? "";
-
- let markerContentViewW : CGFloat = 170
- let mainTitleH : CGFloat = mainTiel.height(withConstrainedWidth: CGFloat(markerContentViewW - 16), font: UIFont.systemFont(ofSize: 10, weight: .bold))
- let markerContentViewH : CGFloat = CGFloat(mainTitleH) + 8 + 14 + 5 + 8
- bubbleHeight = markerContentViewH;
- //let markerSize = CGSize(width: markerContentViewW, height: markerContentViewH)
-
-
- // 设置图像视图约束 - 居中显示在标记视图中
- guard let markerContentView = markerContentView else { return }
- markerContentView.translatesAutoresizingMaskIntoConstraints = false
- NSLayoutConstraint.activate([
- markerContentView.centerXAnchor.constraint(equalTo: centerXAnchor),
- markerContentView.centerYAnchor.constraint(equalTo: centerYAnchor),
- markerContentView.widthAnchor.constraint(equalToConstant: markerContentViewW),
- markerContentView.heightAnchor.constraint(equalToConstant: markerContentViewH)
- ])
-
- // 标题(动态高度)
- NSLayoutConstraint.activate([
- titleLabelView.topAnchor.constraint(equalTo: markerContentView.topAnchor, constant: 8),
- titleLabelView.leadingAnchor.constraint(equalTo: markerContentView.leadingAnchor, constant: 8),
- titleLabelView.trailingAnchor.constraint(equalTo: markerContentView.trailingAnchor, constant: -8),
- titleLabelView.heightAnchor.constraint(equalToConstant: mainTitleH)
- // 移除固定高度约束,让标题根据内容自动调整
- ])
- // 底部区域(动态高度)
- NSLayoutConstraint.activate([
- bottomView.topAnchor.constraint(equalTo: titleLabelView.bottomAnchor, constant: 5),
- bottomView.leadingAnchor.constraint(equalTo: markerContentView.leadingAnchor, constant: 8),
- bottomView.trailingAnchor.constraint(equalTo: markerContentView.trailingAnchor, constant: -8),
- bottomView.bottomAnchor.constraint(equalTo: markerContentView.bottomAnchor, constant: -8)
- // 移除固定高度约束,让底部视图根据内容自动调整
- ])
-
- // 设置整个视图的高度(包含三角形)和最小宽度
- NSLayoutConstraint.activate([
- heightAnchor.constraint(equalToConstant: bubbleHeight + 6),
- widthAnchor.constraint(greaterThanOrEqualToConstant: markerContentViewW)
- ])
-
- layoutIfNeeded()
- updateTrianglePosition()
-
- // 更新偏移量
- //updateCenterOffset()
- }
-
- private func readImageContentFrom(imageName : String) -> UIImage {
- if let image = UIImage(named: imageName) {
- return image
- }
-
- // 尝试从插件资源束加载
- let bundleURL = Bundle(for: MapAnnotationView.self).url(forResource: "map_amap_ios_image_source", withExtension: "bundle")
- if let bundleURL = bundleURL, let resourceBundle = Bundle(url: bundleURL) {
- return UIImage(named: imageName, in: resourceBundle, compatibleWith: nil) ?? UIImage()
- }
-
- return UIImage()
- }
-
-
- // MARK: - 更新视图
-
- private func updateCenterOffset() {
- let markerSize = CGSize(width: bubbleHeight + 6, height: 30)
-
- // 没有文本时,仅需要将图片底部对准坐标点
- centerOffset = CGPoint(x: 0, y: -markerSize.height/2)
- }
- override func setSelected(_ selected: Bool, animated: Bool) {
- super.setSelected(selected, animated: animated)
- }
-
-
- override func layoutSubviews() {
- super.layoutSubviews()
- updateTrianglePosition()
- updateCenterOffset()
- }
-
- private func updateTrianglePosition() {
- // 更新三角形位置到底部中心
- let width = bounds.width
- triangleLayer.frame = CGRect(x: (width - 10) / 2, y: bubbleHeight + 3, width: 10, height: triangleHeight)
- }
- }
|