// // RemoveMemberView.swift // QuickLocation // // Created by 八条 on 2026/6/12. // import UIKit final class RemoveMemberView: UIView { static let rowHeight: CGFloat = 52 private var listHeightConstraint: NSLayoutConstraint? override init(frame: CGRect) { super.init(frame: frame) backgroundColor = UIColor(hexStr: "#F7F7F7") setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { addSubview(navView) addSubview(searchField) addSubview(titleLab) addSubview(listContainerView) listContainerView.addSubview(tableView) navView.layoutChain .top() .edgesHorzontal() .height(kNaviHeight) searchField.layoutChain .topToBottomOfView(navView, offset: 20) .edgesHorzontal(15) .height(38) searchField.addSubview(searchPlaceholderView) searchPlaceholderView.layoutChain .center() .height(20) searchPlaceholderView.layoutChain.width(52) titleLab.layoutChain .topToBottomOfView(searchField, offset: 19) .left(16) .height(19) listContainerView.layoutChain .topToBottomOfView(titleLab, offset: 6) .edgesHorzontal(15) tableView.layoutChain.edges() listHeightConstraint = listContainerView.jh_setDimension(.height, toSize: 0) } func updateMemberCount(_ count: Int) { let prefix = "圈成员" let countText = "(\(count)人)" let text = prefix + countText let attributedText = NSMutableAttributedString(string: text) attributedText.addAttributes([ .font: UIFont.systemFont(ofSize: 14, weight: .medium), .foregroundColor: UIColor(hexStr: "#6E6E73") ], range: NSRange(location: 0, length: text.count)) attributedText.addAttributes([ .font: UIFont.systemFont(ofSize: 13, weight: .regular), .foregroundColor: UIColor(hexStr: "#8E8E93") ], range: NSRange(location: prefix.count, length: countText.count)) titleLab.attributedText = attributedText } func updateHeight(itemCount: Int) { let contentHeight = CGFloat(itemCount) * Self.rowHeight layoutIfNeeded() let bottomInset = max(kSafeBottomMargin, safeAreaInsets.bottom) let maxHeight = max(0, bounds.height - listContainerView.frame.minY - bottomInset) listHeightConstraint?.constant = min(contentHeight, maxHeight) tableView.isScrollEnabled = contentHeight >= maxHeight && itemCount > 0 listContainerView.isHidden = itemCount == 0 layoutIfNeeded() } func updateSearchPlaceholder(isHidden: Bool) { searchPlaceholderView.isHidden = isHidden } lazy var navView: BaseNavigationView = { let nav = BaseNavigationView(title: "圈子成员") nav.addRightButton(deleteBtn) return nav }() lazy var deleteBtn: UIButton = { let button = UIButton(type: .custom) button.setTitle("移除", for: .normal) button.setTitleColor(UIColor(hexStr: "#FF4D53"), for: .normal) button.setTitleColor(UIColor(hexStr: "#FF4D53", alpha: 0.35), for: .disabled) button.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium) button.contentHorizontalAlignment = .right button.isEnabled = false return button }() lazy var searchField: UISearchTextField = { let textField = UISearchTextField() textField.backgroundColor = .white textField.borderStyle = .none textField.cornerRadius = 11 textField.clipsToBounds = true textField.font = .systemFont(ofSize: 14) textField.textColor = UIColor(hexStr: "#293445") textField.tintColor = UIColor(hexStr: "#293445") textField.returnKeyType = .search textField.clearButtonMode = .whileEditing textField.textAlignment = .left textField.leftView = UIView(frame: .zero) textField.leftViewMode = .never return textField }() private lazy var searchPlaceholderView: UIView = { let view = UIView() view.isUserInteractionEnabled = false let imageView = UIImageView(image: UIImage(named: "Group/remove_member_search")) imageView.contentMode = .scaleAspectFit view.addSubview(imageView) imageView.layoutChain .left() .centerY() .width(16) .height(16) let label = UILabel() label.text = "搜索" label.textColor = UIColor(hexStr: "#B0B0B5") label.font = .systemFont(ofSize: 14) view.addSubview(label) label.layoutChain .leftToRightOfView(imageView, offset: 6) .right() .centerY() return view }() private lazy var titleLab = UILabel() private lazy var listContainerView: UIView = { let view = UIView() view.backgroundColor = .white view.cornerRadius = 10 view.clipsToBounds = true return view }() lazy var tableView: UITableView = { let tableView = UITableView(frame: .zero, style: .plain) tableView.backgroundColor = .clear tableView.separatorStyle = .none tableView.rowHeight = Self.rowHeight tableView.estimatedRowHeight = Self.rowHeight tableView.isScrollEnabled = false tableView.showsVerticalScrollIndicator = false tableView.keyboardDismissMode = .onDrag tableView.register(RemoveMemberCell.self) return tableView }() } // MARK: - RemoveMemberCell final class RemoveMemberCell: UITableViewCell { func configure( _ model: GroupMemberModel, isOwn: Bool, isSelected: Bool, showsSeparator: Bool ) { avatarImageView.image = model.userIcon nameLab.text = model.nick_name selectedBtn.isHidden = false selectedBtn.isSelected = isOwn ? false : isSelected selectedBtn.alpha = isOwn ? 0.45 : 1 lineView.isHidden = !showsSeparator } override init(style: CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none backgroundColor = .clear contentView.backgroundColor = .clear setupSubviews() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupSubviews() { contentView.addSubview(avatarImageView) contentView.addSubview(nameLab) contentView.addSubview(selectedBtn) contentView.addSubview(lineView) avatarImageView.layoutChain .left(16) .centerY() .width(38) .height(38) nameLab.layoutChain .leftToRightOfView(avatarImageView, offset: 12) .centerY() selectedBtn.layoutChain .right(14) .centerY() .width(24) .height(24) lineView.layoutChain .left(20) .right(13) .bottom() .height(0.5) } private lazy var avatarImageView: UIImageView = { let imageView = UIImageView() imageView.backgroundColor = UIColor(hexStr: "#F2F2F2") imageView.contentMode = .scaleAspectFill imageView.cornerRadius = 9 imageView.clipsToBounds = true return imageView }() private lazy var nameLab: UILabel = { let label = UILabel() label.textColor = UIColor(hexStr: "#111111") label.font = .systemFont(ofSize: 15, weight: .regular) label.lineBreakMode = .byTruncatingTail return label }() private lazy var selectedBtn: UIButton = { let button = UIButton(type: .custom) button.setImage(UIImage(named: "Group/remove_member_unselected"), for: .normal) button.setImage(UIImage(named: "Group/remove_member_selected"), for: .selected) button.isUserInteractionEnabled = false return button }() private lazy var lineView: UIView = { let view = UIView() view.backgroundColor = UIColor(hexStr: "#EEEEF0") return view }() }