// // GroupChooseView.swift // QuickLocation // // Created by 八条 on 2026/6/27. // import UIKit import ObjectMapper class GroupChooseView: UIView { private static let shared = GroupChooseView(frame: CGRect(origin: .zero, size: kScreenSize)) private var groupModel: GroupModel? { didSet { guard let model = groupModel else { return } groupList = model.groups let count = min(model.groups.count, 5) tableView.isScrollEnabled = model.groups.count > 5 tableView.layoutChain.height(CGFloat(count * 68), relation: .greaterThanOrEqual) } } private var groupInfo: [String: Any] { guard let model = groupModel, let groupInfoModel = model.groups.first(where: { $0.group_key == defaultGroupKey }) else { return [:] } return groupInfoModel.toJSON() } private var defaultGroupKey: String = "" { didSet { tableView.reloadData() } } private var groupList: [GroupInfoModel] = [] { didSet { tableView.reloadData() } } private var completion: ((String?) -> Void)? @objc func tap() { completion?(nil) } @objc func cancelAction(button: UIButton) { completion?(nil) } @objc func inviteAction(button: UIButton) { completion?(nil) AppRouter.push(Route.inviteJoin, userInfo: ["groupInfo": self.groupInfo]) } private lazy var bgView: UIView = { let view = UIView() view.backgroundColor = .black.withAlphaComponent(0.5) view.clipsToBounds = true return view }() lazy var infoView: UIView = { let view = UIView() view.backgroundColor = .white view.layer.cornerRadius = 10 view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] return view }() lazy var titleLab: UILabel = { let label = UILabel() label.text = "选择圈子" label.font = .systemFont(ofSize: 16, weight: .bold) label.textColor = ThemeManager.shared.color.titleAuxColor return label }() 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(GroupListCell.self) tableView.tableHeaderView = UIView(frame: CGRectMake(0, 0, kScreenWidth, 10)) tableView.dataSource = self tableView.delegate = self return tableView }() lazy var cancelBtn: UIButton = { let btn = UIButton(type: .custom) btn.setTitle("取消", for: .normal) btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 15, weight: .medium) btn.backgroundColor = .white btn.borderWidth = 1 btn.borderColor = UIColor(hexStr: "#16B3FF") btn.cornerRadius = 20 btn.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) return btn }() lazy var inviteBtn: UIButton = { let btn = UIButton(type: .custom) btn.setTitle("邀请", for: .normal) btn.setTitleColor(.white, for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) btn.cornerRadius = 20 btn.addTarget(self, action: #selector(inviteAction), for: .touchUpInside) return btn }() override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear addSubview(bgView) bgView.addSubview(infoView) infoView.addSubview(titleLab) infoView.addSubview(tableView) infoView.addSubview(cancelBtn) infoView.addSubview(inviteBtn) // bgView 全屏 bgView.layoutChain.edges() // infoView 横向撑满,底部对齐,高度由内容决定 infoView.layoutChain .edgesHorzontal() .bottom() titleLab.layoutChain .top(16) .left(12) cancelBtn.layoutChain .left(15) .bottom(20 + kSafeBottomMargin) .widthToView(inviteBtn) .height(44) inviteBtn.layoutChain .leftToRightOfView(cancelBtn, offset: 7) .right(15) .bottomToView(cancelBtn) .height(44) .widthToView(inviteBtn) tableView.layoutChain .topToBottomOfView(titleLab, offset: 10) .edgesHorzontal() .bottomToTopOfView(cancelBtn, offset: -17) .height(78, relation: .greaterThanOrEqual) 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 GroupChooseView { /// 显示选择弹窗(底部弹出) static func show(groupModel: GroupModel, completion: @escaping ((String?) -> Void)) { guard let superView = kKeyWindow else { return } let shared = GroupChooseView.shared if shared.superview != nil { shared.removeFromSuperview() } shared.groupModel = groupModel shared.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight) superView.addSubview(shared) superView.bringSubviewToFront(shared) shared.bgView.alpha = 0 shared.infoView.transform = CGAffineTransform(translationX: 0, y: shared.infoView.frame.maxY + 100) shared.completion = { text in completion(text) GroupChooseView.dismiss() } shared.layoutIfNeeded() UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut) { shared.bgView.alpha = 1 shared.infoView.transform = .identity } } /// 关闭(底部滑出) static func dismiss() { guard GroupChooseView.shared.superview != nil else { return } let shared = GroupChooseView.shared UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseIn) { shared.bgView.alpha = 0 shared.infoView.transform = CGAffineTransform(translationX: 0, y: shared.infoView.frame.maxY + 100) } completion: { _ in shared.removeFromSuperview() shared.infoView.transform = .identity } } } // MARK: - UIGestureRecognizerDelegate extension GroupChooseView: 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 GroupChooseView: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { groupList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: GroupListCell = 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) { defaultGroupKey = groupList[indexPath.row].group_key } }