// // MapAmapMarkerBatteryView.swift // map_amap_ios // // Created by 诺诺诺的言 on 2025/7/22. // import Foundation import UIKit class MapAmapMarkerBatteryView: UIView { // 电池百分比 (0-100) var percentage: Int = 100 { didSet { percentage = min(100, max(0, percentage)) setNeedsDisplay() } } // 电池颜色 var batteryColor: UIColor = { if #available(iOS 13.0, *) { return .systemGreen } else { return UIColor(red: 0.20, green: 0.78, blue: 0.35, alpha: 1.00) } }() { didSet { setNeedsDisplay() } } // 低电量颜色 (默认低于20%显示红色) var lowBatteryColor: UIColor = { if #available(iOS 13.0, *) { return .systemRed } else { return UIColor(red: 1.00, green: 0.23, blue: 0.19, alpha: 1.00) } }() var lowBatteryThreshold: Int = 20 // 边框颜色 var borderColor: UIColor = { if #available(iOS 13.0, *) { return .label } else { return .black } }() { didSet { setNeedsDisplay() } } // 边框宽度 var borderWidth: CGFloat = 1.0 { didSet { setNeedsDisplay() } } // 内容与边框的间距 var contentPadding: CGFloat = 1.0 { didSet { setNeedsDisplay() } } // 电池头与电池身体的间距 var headSpacing: CGFloat = 1.0 { didSet { setNeedsDisplay() } } // 是否显示百分比文本 var showPercentageText: Bool = true { didSet { setNeedsDisplay() } } // 文本颜色 var textColor: UIColor = { if #available(iOS 13.0, *) { return .label } else { return .black } }() { didSet { setNeedsDisplay() } } // 文本字体 var textFont: UIFont = UIFont.systemFont(ofSize: 10) { didSet { setNeedsDisplay() } } // 文本与电池的间距 var textSpacing: CGFloat = 2 { didSet { setNeedsDisplay() } } // 边距设置 var horizontalPadding: CGFloat = 6 { didSet { setNeedsDisplay() } } var verticalPadding: CGFloat = 4 { didSet { setNeedsDisplay() } } // 电池尺寸 var batteryWidth: CGFloat = 10 { didSet { setNeedsDisplay() } } var batteryHeight: CGFloat = 7 { didSet { setNeedsDisplay() } } private let batteryCornerRadius: CGFloat = 1.0 private let batteryKnobWidth: CGFloat = 2.0 private let batteryKnobHeight: CGFloat = 3.0 private let batteryKnobCornerRadius: CGFloat = 0 override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear } required init?(coder: NSCoder) { super.init(coder: coder) backgroundColor = .clear } override func draw(_ rect: CGRect) { super.draw(rect) // 先计算文本尺寸(如果需要显示文本) var textSize = CGSize.zero if showPercentageText { let text = "\(percentage)%" let textAttributes: [NSAttributedString.Key: Any] = [ .font: textFont, .foregroundColor: textColor ] textSize = text.size(withAttributes: textAttributes) } // 计算总内容宽度 let totalContentWidth = batteryWidth + batteryKnobWidth + headSpacing + (showPercentageText ? (textSpacing + textSize.width) : 0) // 计算起始X坐标(居中) let startX = (rect.width - totalContentWidth) / 2 // 电池主体区域 let batteryBodyRect = CGRect( x: startX, y: (rect.height - batteryHeight) / 2, width: batteryWidth, height: batteryHeight ) // 电池头区域 let batteryKnobRect = CGRect( x: batteryBodyRect.maxX + headSpacing, y: batteryBodyRect.midY - batteryKnobHeight / 2, width: batteryKnobWidth, height: batteryKnobHeight ) // 绘制电池主体 let batteryPath = UIBezierPath( roundedRect: batteryBodyRect, cornerRadius: batteryCornerRadius ) batteryPath.lineWidth = borderWidth // 根据电量选择颜色 let fillColor = percentage <= lowBatteryThreshold ? lowBatteryColor : batteryColor fillColor.setStroke() batteryPath.stroke() // 绘制电池头 let knobPath = UIBezierPath( roundedRect: batteryKnobRect, cornerRadius: batteryKnobCornerRadius ) fillColor.setFill() knobPath.fill() // 计算电量填充区域(考虑内容间距) let fillWidth = (batteryWidth - borderWidth - contentPadding * 2) * CGFloat(percentage) / 100 let fillRect = CGRect( x: batteryBodyRect.origin.x + borderWidth / 2 + contentPadding, y: batteryBodyRect.origin.y + borderWidth / 2 + contentPadding, width: fillWidth, height: batteryHeight - borderWidth - contentPadding * 2 ) fillColor.setFill() UIBezierPath(rect: fillRect).fill() // 绘制百分比文本(在电池右侧) if showPercentageText { let text = "\(percentage)%" let textAttributes: [NSAttributedString.Key: Any] = [ .font: textFont, .foregroundColor: fillColor ] let textRect = CGRect( x: batteryKnobRect.maxX + textSpacing, y: rect.midY - textSize.height / 2, width: textSize.width, height: textSize.height ) text.draw(in: textRect, withAttributes: textAttributes) } } override var intrinsicContentSize: CGSize { var textWidth: CGFloat = 0 if showPercentageText { textWidth = "100%".size(withAttributes: [.font: textFont]).width + textSpacing } let totalWidth = batteryWidth + batteryKnobWidth + headSpacing + textWidth let totalHeight = max(batteryHeight, batteryKnobHeight) let sumHeight = totalHeight + verticalPadding * 2 self.layer.cornerRadius = sumHeight / 2.0 self.layer.masksToBounds = true print("totalheigdfdfji---\(totalHeight + verticalPadding * 2)"); return CGSize( width: totalWidth + horizontalPadding * 2, height: totalHeight + verticalPadding * 2 ) } }