// // FeatureIntroView.swift // QuickLocation // import UIKit struct FeatureIntroItem { let title: String let subtitle: String let background: UIColor let titleColor: UIColor let subtitleColor: UIColor let arrowTint: UIColor let action: FeatureIntroAction } enum FeatureIntroAction { case signIn case createBubble case lockDistract case searchLocation case sos case placeholder } final class FeatureIntroView: UIView { var onTapItem: ((FeatureIntroAction) -> Void)? private let headerTitleLab = UILabel() private let headerSubLab = UILabel() private let sheet = UIView() private let grid = UIStackView() private let items: [FeatureIntroItem] = [ FeatureIntroItem( title: "还在吗?", subtitle: "每日打卡签到 记录美好生活", background: UIColor(hexStr: "#EDE7FF"), titleColor: UIColor(hexStr: "#5B4B8A"), subtitleColor: UIColor(hexStr: "#8B7BB8"), arrowTint: UIColor(hexStr: "#7B6AAE"), action: .signIn ), FeatureIntroItem( title: "隐身气泡", subtitle: "只想做个淡人 默默隐身", background: UIColor(hexStr: "#D9ECFF"), titleColor: UIColor(hexStr: "#2F6FAE"), subtitleColor: UIColor(hexStr: "#6A9BC4"), arrowTint: UIColor(hexStr: "#3E8FD0"), action: .createBubble ), FeatureIntroItem( title: "一键锁机", subtitle: "专注当下 拒绝手机干扰", background: UIColor(hexStr: "#DDF5E8"), titleColor: UIColor(hexStr: "#2F8A5B"), subtitleColor: UIColor(hexStr: "#6AAD88"), arrowTint: UIColor(hexStr: "#3EAE72"), action: .lockDistract ), FeatureIntroItem( title: "飞鸽传书", subtitle: "实时查看位置 守护安全出行", background: UIColor(hexStr: "#FFF3D6"), titleColor: UIColor(hexStr: "#A67C2D"), subtitleColor: UIColor(hexStr: "#C4A46A"), arrowTint: UIColor(hexStr: "#C9953A"), action: .placeholder ), FeatureIntroItem( title: "查位置", subtitle: "实时查看位置 守护安全出行", background: UIColor(hexStr: "#D6F4F2"), titleColor: UIColor(hexStr: "#2A8A84"), subtitleColor: UIColor(hexStr: "#66B0AB"), arrowTint: UIColor(hexStr: "#35A8A0"), action: .searchLocation ), FeatureIntroItem( title: "SOS", subtitle: "紧急求助 一键呼叫", background: UIColor(hexStr: "#FFE4E8"), titleColor: UIColor(hexStr: "#D6455D"), subtitleColor: UIColor(hexStr: "#E28A98"), arrowTint: UIColor(hexStr: "#E2556C"), action: .sos ) ] override init(frame: CGRect) { super.init(frame: frame) backgroundColor = UIColor(hexStr: "#F0F1F3") setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { headerTitleLab.text = "功能介绍" headerTitleLab.font = .systemFont(ofSize: 28, weight: .bold) headerTitleLab.textColor = UIColor(hexStr: "#1F2A44") addSubview(headerTitleLab) headerTitleLab.layoutChain.top(kStatusBarHeight + 20).left(20) headerSubLab.text = "视频+图片" headerSubLab.font = .systemFont(ofSize: 28, weight: .bold) headerSubLab.textColor = UIColor(hexStr: "#1F2A44") addSubview(headerSubLab) headerSubLab.layoutChain.topToBottomOfView(headerTitleLab, offset: 2).left(20) sheet.backgroundColor = .white sheet.layer.cornerRadius = 28 sheet.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] sheet.clipsToBounds = true addSubview(sheet) sheet.layoutChain .topToBottomOfView(headerSubLab, offset: 24) .edgesHorzontal() .bottom() grid.axis = .vertical grid.spacing = 12 grid.distribution = .fillEqually sheet.addSubview(grid) grid.layoutChain .top(24) .edgesHorzontal(16) .bottom(24 + 70) // leave room for custom tab bar for row in 0..<3 { let rowStack = UIStackView() rowStack.axis = .horizontal rowStack.spacing = 12 rowStack.distribution = .fillEqually for col in 0..<2 { let item = items[row * 2 + col] let card = FeatureIntroCardView(item: item) card.addTarget(self, action: #selector(cardTapped(_:)), for: .touchUpInside) card.tag = row * 2 + col rowStack.addArrangedSubview(card) } grid.addArrangedSubview(rowStack) } } @objc private func cardTapped(_ sender: FeatureIntroCardView) { let idx = sender.tag guard items.indices.contains(idx) else { return } onTapItem?(items[idx].action) } } final class FeatureIntroCardView: UIControl { private let titleLab = UILabel() private let subLab = UILabel() private let arrowBtn = UIView() init(item: FeatureIntroItem) { super.init(frame: .zero) backgroundColor = item.background layer.cornerRadius = 20 clipsToBounds = true titleLab.text = item.title titleLab.font = .systemFont(ofSize: 18, weight: .bold) titleLab.textColor = item.titleColor addSubview(titleLab) titleLab.layoutChain.top(16).left(14).right(14) subLab.text = item.subtitle subLab.font = .systemFont(ofSize: 11, weight: .medium) subLab.textColor = item.subtitleColor subLab.numberOfLines = 2 addSubview(subLab) subLab.layoutChain.topToBottomOfView(titleLab, offset: 6).left(14).right(14) arrowBtn.backgroundColor = .white arrowBtn.isUserInteractionEnabled = false arrowBtn.layer.cornerRadius = 14 addSubview(arrowBtn) arrowBtn.layoutChain.left(14).bottom(14).width(28).height(28) let arrow = UIImageView(image: UIImage(systemName: "chevron.right")) arrow.tintColor = item.arrowTint arrow.contentMode = .scaleAspectFit arrowBtn.addSubview(arrow) arrow.layoutChain.center().width(10).height(12) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }