// // CreateGroupView.swift // QuickLocation // // Created by 八条 on 2026/6/2. // import UIKit import RxSwift import RxCocoa class CreateGroupView: UIView { var disposeBag = DisposeBag() private let limitCount = 50 private func setupRx() { groupNameTF.rx.text.orEmpty .subscribe(onNext: { [weak self] text in guard let self = self else { return } if text.count > 10 { self.groupNameTF.text = String(text.prefix(10)) } }) .disposed(by: disposeBag) Observable.merge( groupContentTV.rx.didChange.asObservable(), groupContentTV.rx.text.map { _ in () }, groupContentTV.rx.methodInvoked(#selector(UITextView.paste(_:))).map { _ in () } ) .throttle(.milliseconds(100), scheduler: MainScheduler.instance) .subscribe(onNext: { [weak self] in guard let self = self else { return } let count = self.groupContentTV.text.count self.placeholderLab.isHidden = count != 0 if count > self.limitCount { self.groupContentTV.text = String(self.groupContentTV.text.prefix(self.limitCount)) self.groupContentTV.selectedRange = NSRange(location: self.limitCount, length: 0) return } }) .disposed(by: disposeBag) backBtn.rx.tap.subscribe(onNext: { _ in AppRouter.shared.popOrDismiss() }).disposed(by: disposeBag) } private func setupUI() { addSubview(navBgView) addSubview(navBarView) navBarView.addSubview(navTitleLabel) navBarView.addSubview(backBtn) addSubview(submitBtn) addSubview(titleLab) addSubview(infoView) infoView.addSubview(groupNameInputView) groupNameInputView.addSubview(groupNameTitleLab) groupNameInputView.addSubview(groupNameTF) infoView.addSubview(groupIconInputView) groupIconInputView.addSubview(groupIconTitleLab) groupIconInputView.addSubview(groupIconImgView) infoView.addSubview(groupContentInputView) groupContentInputView.addSubview(groupContentTitleLab) groupContentInputView.addSubview(groupContentTV) groupContentInputView.addSubview(placeholderLab) infoView.addSubview(tagInfoView) tagInfoView.addSubview(tagTitleLab) tagInfoView.addSubview(tagView) tagInfoView.addSubview(tipsLab) navBgView.layoutChain .edges(excludingEdge: .bottom) .heightToWidth(160/375) navBarView.layoutChain .edges(excludingEdge: .bottom) .height(kNaviHeight) navTitleLabel.layoutChain .top(kStatusBarHeight + 12) .centerY(backBtn) .centerX() backBtn.layoutChain .centerY(navTitleLabel) .left(15) .width(24) .height(24) titleLab.layoutChain .topToBottomOfView(navBarView, offset: 20) .left(15) submitBtn.layoutChain .bottom(kSafeBottomMargin + 36) .centerX() .edgesHorzontal(30) .height(50) infoView.layoutChain .topToBottomOfView(titleLab, offset: 20) .edgesHorzontal(15) groupNameInputView.layoutChain .edges(excludingEdge: .bottom) groupNameTitleLab.layoutChain .left(15) .centerY() .width(50) groupNameTF.layoutChain .edgesVertical() .leftToRightOfView(groupNameTitleLab, offset: 20) .right(43) groupIconInputView.layoutChain .topToBottomOfView(groupNameInputView) .leftToView(groupNameInputView) .rightToView(groupNameInputView) groupIconTitleLab.layoutChain .left(15) .centerY() .width(50) groupIconImgView.layoutChain .leftToRightOfView(groupIconTitleLab, offset: 20) .edgesVertical(10) .width(40) .height(40) groupContentInputView.layoutChain .topToBottomOfView(groupIconInputView) .leftToView(groupNameInputView) .rightToView(groupNameInputView) groupContentTitleLab.layoutChain .top(20) .left(15) .width(50) groupContentTV.layoutChain .topToView(groupContentTitleLab, offset: -9) .leftToRightOfView(groupContentTitleLab, offset: 18) .right(52) .bottom(10) .height(20, relation: .greaterThanOrEqual) placeholderLab.layoutChain .topToView(groupContentTV, offset: 8) .leftToView(groupContentTV, offset: 5) tagInfoView.layoutChain .topToBottomOfView(groupContentInputView) .leftToView(groupNameInputView) .rightToView(groupNameInputView) .bottom(20) tagTitleLab.layoutChain .top(20) .left(15) tagView.layoutChain .topToBottomOfView(tagTitleLab, offset: 10) .edgesHorzontal(15) .height(64) tipsLab.layoutChain .topToBottomOfView(tagView, offset: 10) .left(15) .bottom() } 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 view = UIView() view.backgroundColor = .clear return view }() lazy var navTitleLabel: UILabel = { let label = UILabel() label.text = "创建圈子" label.font = .systemFont(ofSize: 18, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor label.textAlignment = .center return label }() lazy var backBtn: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "Common/back"), for: .normal) btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 100, right: 100) return btn }() lazy var titleLab: UILabel = { let label = UILabel() label.text = "编辑信息" label.font = .systemFont(ofSize: 14, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor return label }() lazy var infoView: UIView = { let view = UIView() view.backgroundColor = UIColor(hexStr: "#F5FBFF") view.cornerRadius = 10 return view }() // 圈子名称 lazy var groupNameInputView: UIView = { let view = UIView() view.backgroundColor = .clear let icon = UIImageView() icon.image = UIImage(named: "Group/edit") view.addSubview(icon) icon.layoutChain .right(15) .edgesVertical(20) .width(20) .height(20) let line = UIView() line.backgroundColor = UIColor(hexStr: "#EEEEEE") view.addSubview(line) line.layoutChain .edgesHorzontal(15) .height(0.5) .bottom() return view }() lazy var groupNameTitleLab: UILabel = { let label = UILabel() label.text = "圈子名称" label.font = .systemFont(ofSize: 12, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor return label }() lazy var groupNameTF: UITextField = { let textField = UITextField(frame: .zero) textField.font = UIFont.systemFont(ofSize: 14, weight: .medium) textField.textColor = ThemeManager.shared.color.titleAuxColor textField.placeholderColor(placeholder: "请输入圈子名称", color: UIColor(hexStr: "#999999", alpha: 1.0)) return textField }() // 圈子图标 lazy var groupIconInputView: UIView = { let view = UIView() view.backgroundColor = .clear let icon = UIImageView() icon.image = UIImage(named: "Group/arrow") view.addSubview(icon) icon.layoutChain .right(15) .centerY() .width(14) .height(14) let line = UIView() line.backgroundColor = UIColor(hexStr: "#EEEEEE") view.addSubview(line) line.layoutChain .edgesHorzontal(15) .height(0.5) .bottom() return view }() lazy var groupIconTitleLab: UILabel = { let label = UILabel() label.text = "圈子图标" label.font = .systemFont(ofSize: 12, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor return label }() lazy var groupIconImgView: UIImageView = { let view = UIImageView() view.image = UIImage(named: "GroupIcon/1") view.contentMode = .scaleAspectFill return view }() // 圈子描述 lazy var groupContentInputView: UIView = { let view = UIView() view.backgroundColor = .clear let icon = UIImageView() icon.image = UIImage(named: "Group/edit") view.addSubview(icon) icon.layoutChain .top(20) .right(15) .width(20) .height(20) let line = UIView() line.backgroundColor = UIColor(hexStr: "#EEEEEE") view.addSubview(line) line.layoutChain .edgesHorzontal(15) .height(0.5) .bottom() return view }() lazy var groupContentTitleLab: UILabel = { let label = UILabel() label.text = "圈子描述" label.font = .systemFont(ofSize: 12, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor return label }() lazy var groupContentTV: UITextView = { let textView = UITextView() textView.backgroundColor = .clear textView.font = .systemFont(ofSize: 14, weight: .medium) textView.textColor = ThemeManager.shared.color.titleAuxColor textView.isScrollEnabled = false return textView }() lazy var placeholderLab: UILabel = { let label = UILabel() label.text = "请输入圈子描述" label.textColor = ThemeManager.shared.color.contentColor label.font = .systemFont(ofSize: 14, weight: .medium) return label }() // 标签 lazy var tagInfoView: UIView = { let view = UIView() view.backgroundColor = .clear return view }() lazy var tagTitleLab: UILabel = { let label = UILabel() label.text = "选择标签" label.font = .systemFont(ofSize: 12, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor return label }() lazy var tagView: UICollectionView = { let layout = UICollectionViewFlowLayout() let cvWidth = kScreenWidth - 60 let spacing: CGFloat = 6 let itemW = (cvWidth - spacing * 3) / 4 layout.itemSize = CGSize(width: itemW, height: 27) layout.minimumInteritemSpacing = spacing layout.minimumLineSpacing = 10 let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.backgroundColor = .clear cv.isScrollEnabled = false cv.register(TagCell.self) return cv }() lazy var tipsLab: UILabel = { let label = UILabel() label.text = "如选择为私密圈子,将不能被分享到探索和被搜索。" label.textColor = ThemeManager.shared.color.contentColor label.font = .systemFont(ofSize: 10, weight: .regular) return label }() lazy var submitBtn: 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 = 25 return btn }() override init(frame: CGRect) { super.init(frame: .zero) backgroundColor = .white setupUI() setupRx() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } // MARK: - TagCell final class TagCell: UICollectionViewCell { static let reuseId = "TagCell" private let label: UILabel = { let l = UILabel() l.font = .systemFont(ofSize: 12, weight: .medium) l.textAlignment = .center return l }() private var isTagSelected = false override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(label) label.layoutChain.edges() contentView.layer.cornerRadius = 4 contentView.backgroundColor = UIColor(hexStr: "#E3F6FF") updateStyle() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(_ text: String, isSelected: Bool) { label.text = text self.isTagSelected = isSelected updateStyle() } func toggleSelection() { isTagSelected.toggle() updateStyle() } private func updateStyle() { if isTagSelected { label.textColor = UIColor(hexStr: "#16B3FF") contentView.layer.borderWidth = 1 contentView.layer.borderColor = UIColor(hexStr: "#16B3FF").cgColor } else { label.textColor = ThemeManager.shared.color.titleAuxColor contentView.layer.borderWidth = 0 } } }