// // GroupListPopView.swift // QuickLocation // // Created by 八条 on 2026/5/30. // import UIKit class GroupListPopView: UIView { private static let shared = GroupListPopView(frame: CGRect(origin: .zero, size: kScreenSize)) private var groupModel: GroupModel? { didSet { guard let model = groupModel else { return } groupNameLab.text = model.groups.first(where: { $0.group_key == model.default_group_key })?.name ?? "" defaultGroupKey = model.default_group_key groupList = model.groups } } private var defaultGroupKey: String = "" private var groupList: [GroupInfoModel] = [] { didSet { tableView.reloadData() } } /// 完成选中进行回调 private var completion: ((String?) -> Void)? @objc func tap() { completion?(nil) } @objc func createAction(button: UIButton) { completion?(nil) AppRouter.push(Route.createGroup) } @objc func joinAction(button: UIButton) { completion?(nil) AppRouter.push(Route.joinGroup) } private lazy var bgView: UIView = { let view = UIView() view.backgroundColor = .black.withAlphaComponent(0.5) view.clipsToBounds = true return view }() // 圈子选择 lazy var groupView: UIView = { let view = UIView() view.backgroundColor = .white view.cornerRadius = 18 return view }() lazy var groupIconView: UIImageView = { let view = UIImageView() view.image = UIImage(named: "Home/group") view.backgroundColor = .clear view.contentMode = .scaleAspectFill return view }() lazy var groupNameLab: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 16, weight: .medium) label.textColor = UIColor(hexStr: "#0F2846") label.textAlignment = .center return label }() lazy var groupArrowIconView: UIImageView = { let view = UIImageView() view.image = UIImage(named: "Home/arrow_down") view.backgroundColor = .clear view.contentMode = .scaleAspectFill return view }() lazy var infoView: UIView = { let view = UIView() view.backgroundColor = .white view.cornerRadius = 10 return view }() lazy var tableView: UITableView = { let tableView = UITableView(frame: .zero, style: .grouped) tableView.backgroundColor = .white tableView.separatorStyle = .none tableView.estimatedRowHeight = 68 tableView.showsVerticalScrollIndicator = false tableView.bounces = false tableView.isScrollEnabled = false tableView.register(GroupListPopCell.self) tableView.tableHeaderView = UIView(frame: CGRectMake(0, 0, kScreenWidth, 10)) tableView.dataSource = self tableView.delegate = self return tableView }() lazy var createGroupBtn: UIButton = { let btn = UIButton(type: .custom) btn.setTitle("创建圈子", for: .normal) btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) btn.setBackgroundImage(UIImage(named: "Common/gradient_bg"), for: .normal) btn.cornerRadius = 22 btn.addTarget(self, action: #selector(createAction), for: .touchUpInside) return btn }() lazy var joinGroupBtn: UIButton = { let btn = UIButton(type: .custom) btn.setTitle("加入圈子", for: .normal) btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) btn.setBackgroundImage(UIImage(named: "Common/gradient_bg"), for: .normal) btn.cornerRadius = 22 btn.addTarget(self, action: #selector(joinAction), for: .touchUpInside) return btn }() // MARK: - Init override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear addSubview(bgView) bgView.addSubview(infoView) infoView.addSubview(tableView) infoView.addSubview(createGroupBtn) infoView.addSubview(joinGroupBtn) bgView.addSubview(groupView) groupView.addSubview(groupIconView) groupView.addSubview(groupNameLab) groupView.addSubview(groupArrowIconView) groupView.layoutChain .top(59) .height(36) .centerX() .width(185, relation: .greaterThanOrEqual) groupIconView.layoutChain .left(11) .centerY() .width(30) .height(30) groupArrowIconView.layoutChain .right(15) .centerY() .width(15) .height(8.5) groupNameLab.layoutChain .edgesVertical() .leftToRightOfView(groupIconView) .rightToLeftOfView(groupArrowIconView) infoView.layoutChain .topToBottomOfView(groupView, offset: 20) .edgesHorzontal(15) createGroupBtn.layoutChain .left(15) .bottom(20) .widthToView(joinGroupBtn) .height(44) joinGroupBtn.layoutChain .leftToRightOfView(createGroupBtn, offset: 7) .right(15) .bottom(20) .height(44) .widthToView(joinGroupBtn) tableView.layoutChain .edges(excludingEdge: .bottom) .height(78, relation: .greaterThanOrEqual) .bottomToTopOfView(createGroupBtn, offset: -17) let tap = UITapGestureRecognizer(target: self, action: #selector(tap)) tap.delegate = self addGestureRecognizer(tap) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() } } // MARK: - Public extension GroupListPopView { /// 显示选择弹窗 /// - Parameters: /// - start: 显示起始点 static func show(start: CGPoint, groupModel: GroupModel, completion: @escaping ((String?) -> Void)) { guard let superView = kKeyWindow else { return } if GroupListPopView.shared.superview != nil { GroupListPopView.shared.removeFromSuperview() GroupListPopView.shared.bgView.frame = .zero } GroupListPopView.shared.groupModel = groupModel GroupListPopView.shared.bgView.alpha = 1 GroupListPopView.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight) superView.addSubview(GroupListPopView.shared) superView.bringSubviewToFront(GroupListPopView.shared) let viewHeight = CGFloat(GroupListPopView.shared.groupList.count * 68) + 10 + 81 GroupListPopView.shared.tableView.dl.height = viewHeight GroupListPopView.shared.infoView.alpha = 0 GroupListPopView.shared.completion = { (text) in completion(text) GroupListPopView.dismiss() } UIView.animate(withDuration: 0.25) { GroupListPopView.shared.infoView.alpha = 1 // GroupListPopView.shared.infoView.dl.y = start.y } } /// 关闭 static func dismiss() { guard GroupListPopView.shared.superview != nil else { return } let viewHeight = GroupListPopView.shared.infoView.frame.height UIView.animate(withDuration: 0.15) { GroupListPopView.shared.infoView.alpha = 0 // GroupListPopView.shared.infoView.dl.y = -viewHeight } UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) { GroupListPopView.shared.bgView.alpha = 0 } completion: { _ in GroupListPopView.shared.removeFromSuperview() } } } // MARK: - UIGestureRecognizerDelegate extension GroupListPopView: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if let view = touch.view, !(view == self || view == bgView) { return false } return true } } // MARK: - UITableViewDataSource & UITableViewDelegate extension GroupListPopView: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { groupList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: GroupListPopCell = tableView.dequeueReusableCell(for: indexPath) cell.configure(model: groupList[indexPath.row], isSelected: defaultGroupKey == groupList[indexPath.row].group_key) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { completion?(groupList[indexPath.row].group_key) } } // MARK: - GroupListPopCell class GroupListPopCell: UITableViewCell { func configure(model: GroupInfoModel, isSelected: Bool) { avaterImgView.image = model.groupIcon nameLab.text = model.name bgView.isHidden = !isSelected } override init(style: CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none backgroundColor = .clear setupSubviews() } private func setupSubviews() { contentView.addSubview(bgView) contentView.addSubview(avaterImgView) contentView.addSubview(nameLab) bgView.layoutChain.edges() avaterImgView.layoutChain .edgesVertical(14) .left(15) .width(40) .height(40) nameLab.layoutChain .centerY(avaterImgView) .leftToRightOfView(avaterImgView, offset: 11) .right(100, relation: .greaterThanOrEqual) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } lazy var bgView: UIView = { let view = UIView() view.backgroundColor = UIColor(hexStr: "#EFF9FF") let lineView = UIView() lineView.backgroundColor = UIColor(hexStr: "#16B3FF") view.addSubview(lineView) lineView.layoutChain .left() .edgesVertical() .width(6) let selectedIcon = UIImageView() selectedIcon.image = UIImage(named: "Group/selected") view.addSubview(selectedIcon) selectedIcon.layoutChain .right(14) .centerY() .width(24) .height(24) view.isHidden = true return view }() lazy var avaterImgView: UIImageView = { let view = UIImageView() // view.backgroundColor = .lightGray view.contentMode = .scaleAspectFill // view.cornerRadius = 20 return view }() lazy var nameLab: UILabel = { let label = UILabel() label.textColor = ThemeManager.shared.color.titleAuxColor label.font = .systemFont(ofSize: 15, weight: .medium) return label }() }