// // ItineraryTraceView.swift // QuickLocation // // Created by 八条 on 2026/6/30. // import UIKit import RxSwift import RxCocoa import AMapNaviKit class ItineraryTraceView: UIView { var disposeBag = DisposeBag() private func setupRx() { backBtn.rx.tap.subscribe(onNext: { _ in AppRouter.shared.popOrDismiss() }).disposed(by: disposeBag) } private func setupUI() { addSubview(mapView) addSubview(navBgView) addSubview(navBarView) navBarView.addSubview(backBtn) navBarView.addSubview(navTitleLabel) addSubview(playView) addSubview(bottomView) mapView.layoutChain .edges(excludingEdge: .bottom) navBgView.layoutChain .edges(excludingEdge: .bottom) .heightToWidth(160/375) navBarView.layoutChain .edges(excludingEdge: .bottom) .height(kNaviHeight) backBtn.layoutChain .centerY(navTitleLabel) .left(15) .width(24).height(24) navTitleLabel.layoutChain .top(kStatusBarHeight + 12) .centerX() bottomView.layoutChain .edgesHorzontal() .bottom() .height(320 + kSafeBottomMargin) playView.layoutChain .bottomToTopOfView(bottomView, offset: -10) .edgesHorzontal(20) .height(35) mapView.layoutChain.bottomToTopOfView(bottomView, offset: 20) } // MARK: - Views lazy var navBgView: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "Common/navBar_bg_2") iv.contentMode = .scaleAspectFill return iv }() lazy var navBarView: UIView = { let v = UIView() v.backgroundColor = .clear return v }() lazy var backBtn: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "Common/back"), for: .normal) btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 30) return btn }() lazy var navTitleLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 18, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor label.text = "行程轨迹" return label }() lazy var deleteBtn: UIButton = { let btn = UIButton() btn.setImage(UIImage(named: "Common/delete"), for: .normal) btn.extendEdgeInsets = UIEdgeInsets(top: 15, left: 20, bottom: 15, right: 15) btn.isHidden = true return btn }() lazy var mapView: MAMapView! = { let mv = MAMapView() mv.zoomLevel = 14 mv.showsUserLocation = false mv.showsCompass = false mv.userTrackingMode = .none DispatchQueue.main.async { mv.logoCenter = CGPoint(x: mv.bounds.width - 55, y: kNaviHeight) } return mv }() lazy var bottomView: UIView = { let view = UIView() view.backgroundColor = .white view.layer.cornerRadius = 20 view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] view.addSubview(titleLab) titleLab.layoutChain .top(20) .left(20) view.addSubview(startTimeLab) startTimeLab.layoutChain .topToBottomOfView(titleLab, offset: 8) .leftToView(titleLab) let dotView = UIView() dotView.backgroundColor = UIColor(hexStr: "#16B3FF") dotView.cornerRadius = 3 view.addSubview(dotView) dotView.layoutChain .leftToRightOfView(startTimeLab, offset: 10) .centerY(startTimeLab) .width(6) .heightToWidth(1) view.addSubview(startAddressLab) startAddressLab.layoutChain .centerY(startTimeLab) .leftToRightOfView(dotView, offset: 12) let dashedLine = UIImageView(image: UIImage(named: "ItineraryTrace/dashed")) view.addSubview(dashedLine) dashedLine.layoutChain .topToBottomOfView(dotView, offset: 7) .width(2) .height(22) .centerX(dotView) view.addSubview(endTimeLab) view.addSubview(endAddressLab) let endIcon = UIImageView(image: UIImage(named: "ItineraryTrace/end_small")) view.addSubview(endIcon) endIcon.layoutChain .width(10) .height(12) .centerX(dashedLine) .centerY(endTimeLab) endTimeLab.layoutChain .topToBottomOfView(startTimeLab, offset: 24) .leftToView(startTimeLab) endAddressLab.layoutChain .leftToRightOfView(endIcon, offset: 10) .centerY(endTimeLab) let eventTitleLab = UILabel() eventTitleLab.text = "行程事件" eventTitleLab.textColor = UIColor(hexStr: "#0F2846") eventTitleLab.font = .systemFont(ofSize: 16, weight: .semibold) view.addSubview(eventTitleLab) eventTitleLab.layoutChain .topToBottomOfView(endTimeLab, offset: 15) .left(20) view.addSubview(eventCollectionView) eventCollectionView.layoutChain .topToBottomOfView(eventTitleLab, offset: 10) .edgesHorzontal() .bottom(kSafeBottomMargin) return view }() /// 播放 lazy var playView: UIView = { let view = UIView() view.backgroundColor = .clear view.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor view.layer.shadowOffset = CGSize(width: 0, height: 2) view.layer.shadowOpacity = 1 view.layer.shadowRadius = 4 let cornerRadiusView = UIView() cornerRadiusView.backgroundColor = .white cornerRadiusView.cornerRadius = 6 view.addSubview(cornerRadiusView) cornerRadiusView.layoutChain.edges() cornerRadiusView.addSubview(playBtn) cornerRadiusView.addSubview(progressSlider) playBtn.layoutChain .left(12) .centerY() .width(20) .height(20) progressSlider.layoutChain .leftToRightOfView(playBtn, offset: 12) .right(12) .centerY() .height(30) return view }() lazy var playBtn: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "ItineraryTrace/play"), for: .normal) btn.setImage(UIImage(named: "ItineraryTrace/pause"), for: .selected) btn.adjustsImageWhenHighlighted = false return btn }() lazy var progressSlider: UISlider = { let slider = UISlider() slider.minimumValue = 0 slider.maximumValue = 1 slider.value = 0 slider.minimumTrackTintColor = UIColor(hexStr: "#16B3FF") slider.maximumTrackTintColor = UIColor(hexStr: "#E5E5E5") slider.setThumbImage(UIImage(named: "ItineraryTrace/slider"), for: .normal) slider.setThumbImage(UIImage(named: "ItineraryTrace/slider"), for: .highlighted) return slider }() /// xxx 的行程详细信息 lazy var titleLab: UILabel = { let label = UILabel() label.textColor = UIColor(hexStr: "#0F2846") label.font = .systemFont(ofSize: 16, weight: .semibold) return label }() lazy var startTimeLab: UILabel = { let label = UILabel() label.text = " " label.textColor = UIColor(hexStr: "#666666") label.font = .systemFont(ofSize: 16, weight: .medium) return label }() lazy var startAddressLab: UILabel = { let label = UILabel() label.text = " " label.textColor = UIColor(hexStr: "#999999") label.font = .systemFont(ofSize: 14, weight: .medium) return label }() lazy var endTimeLab: UILabel = { let label = UILabel() label.text = " " label.textColor = UIColor(hexStr: "#666666") label.font = .systemFont(ofSize: 16, weight: .medium) return label }() lazy var endAddressLab: UILabel = { let label = UILabel() label.text = " " label.textColor = UIColor(hexStr: "#999999") label.font = .systemFont(ofSize: 14, weight: .medium) return label }() // 行程事件 lazy var eventCollectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: 65, height: 68) layout.minimumLineSpacing = 15 layout.scrollDirection = .vertical layout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.backgroundColor = .clear cv.showsHorizontalScrollIndicator = false cv.isScrollEnabled = false cv.register(ItineraryTraceCell.self) return cv }() func cleanupMap() { #if !targetEnvironment(simulator) mapView?.delegate = nil mapView?.removeFromSuperview() mapView = nil #endif } override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear setupUI() setupRx() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } // MARK: - ItineraryTraceCell 驾驶事件 class ItineraryTraceCell: UICollectionViewCell { func configure(_ item: DrivingEventItem) { nameLab.text = item.title countLab.text = item.count.string } private let bgView: UIView = { let v = UIView() v.backgroundColor = UIColor(hexStr: "#EEF9FF") v.cornerRadius = 10 return v }() lazy var iconView: UIImageView = { let view = UIImageView() view.contentMode = .scaleAspectFill return view }() lazy var nameLab: UILabel = { let l = UILabel() l.font = .systemFont(ofSize: 12, weight: .medium) l.textColor = UIColor(hexStr: "#333333") l.textAlignment = .center return l }() lazy var countLab: UILabel = { let l = UILabel() l.font = .systemFont(ofSize: 14, weight: .medium) l.textColor = UIColor(hexStr: "#38ABFF") l.textAlignment = .center return l }() override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(bgView) bgView.addSubview(countLab) contentView.addSubview(nameLab) bgView.layoutChain .top() .centerX() .width(50) .height(50) countLab.layoutChain.edges() nameLab.layoutChain .topToBottomOfView(bgView, offset: 6) .edgesHorzontal() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }