// // MemberInfoView.swift // QuickLocation // import UIKit import Kingfisher final class MemberInfoView: UIView { lazy var navView = BaseNavigationView(title: "成员信息") let switchGroupBtn: UIButton = { let btn = UIButton(type: .custom) btn.backgroundColor = .white.withAlphaComponent(0.8) btn.setTitle(" 切换圈子 ", for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) btn.setTitleColor(UIColor(hexStr: "#293445"), for: .normal) btn.cornerRadius = 8 return btn }() lazy var memberCV: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal layout.itemSize = CGSize(width: 61, height: 90) layout.minimumLineSpacing = 12 let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.backgroundColor = .white cv.showsHorizontalScrollIndicator = false cv.contentInset = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12) cv.register(GroupMemberListCell.self) cv.layer.cornerRadius = 20 return cv }() let scrollView = UIScrollView() let contentView = UIView() let detailCard = UIView() private let rowsStack = UIStackView() 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) navView.layoutChain.top().edgesHorzontal().height(kNaviHeight) navView.addRightButton(switchGroupBtn) addSubview(scrollView) scrollView.layoutChain.topToBottomOfView(navView).edgesHorzontal().bottom() scrollView.addSubview(contentView) contentView.layoutChain.edges().widthToView(scrollView) contentView.addSubview(memberCV) memberCV.layoutChain.top(8).edgesHorzontal(15).height(100) detailCard.backgroundColor = .white detailCard.layer.cornerRadius = 16 contentView.addSubview(detailCard) detailCard.layoutChain .topToBottomOfView(memberCV, offset: 12) .edgesHorzontal(15) .bottom(24) rowsStack.axis = .vertical rowsStack.spacing = 0 detailCard.addSubview(rowsStack) rowsStack.layoutChain.edges(UIEdgeInsets(top: 4, left: 0, bottom: 4, right: 0)) } func renderRows(_ rows: [MemberInfoRow]) { rowsStack.arrangedSubviews.forEach { rowsStack.removeArrangedSubview($0) $0.removeFromSuperview() } for (i, row) in rows.enumerated() { let view = MemberInfoRowView(row: row) rowsStack.addArrangedSubview(view) view.layoutChain.height(row.kind == .tag ? 56 : 52) if i < rows.count - 1 { let line = UIView() line.backgroundColor = UIColor(hexStr: "#F2F2F2") view.addSubview(line) line.layoutChain.left(15).right(15).bottom(0).height(0.5) } } } } enum MemberInfoRowKind { case text case avatar case tag case disclosure } struct MemberInfoRow { let title: String let value: String let kind: MemberInfoRowKind let action: (() -> Void)? let avatarURL: String? init(title: String, value: String, kind: MemberInfoRowKind = .text, avatarURL: String? = nil, action: (() -> Void)? = nil) { self.title = title self.value = value self.kind = kind self.avatarURL = avatarURL self.action = action } } final class MemberInfoRowView: UIControl { private let titleLab = UILabel() private let valueLab = UILabel() private let arrow = UIImageView(image: UIImage(named: "Mine/arrow_right")) private let avatar = UIImageView() private let tagLab = UILabel() private let actionHandler: (() -> Void)? init(row: MemberInfoRow) { self.actionHandler = row.action super.init(frame: .zero) titleLab.text = row.title titleLab.font = .systemFont(ofSize: 14, weight: .medium) titleLab.textColor = UIColor(hexStr: "#293445") addSubview(titleLab) titleLab.layoutChain.left(15).centerY() valueLab.text = row.value valueLab.font = .systemFont(ofSize: 14, weight: .medium) valueLab.textColor = row.value == "未设置" || row.value == "未绑定" || row.value == "保密" ? UIColor(hexStr: "#AAAAAA") : UIColor(hexStr: "#293445") valueLab.textAlignment = .right arrow.contentMode = .scaleAspectFit avatar.contentMode = .scaleAspectFill avatar.clipsToBounds = true avatar.layer.cornerRadius = 14 tagLab.text = row.value tagLab.font = .systemFont(ofSize: 12, weight: .medium) tagLab.textColor = UIColor(hexStr: "#E8A045") tagLab.backgroundColor = UIColor(hexStr: "#FFF3E0") tagLab.textAlignment = .center tagLab.layer.cornerRadius = 10 tagLab.clipsToBounds = true switch row.kind { case .text: addSubview(valueLab) valueLab.layoutChain.right(15).centerY().leftToRightOfView(titleLab, offset: 12) case .disclosure: addSubview(arrow) arrow.layoutChain.right(15).centerY().width(12).height(12) addSubview(valueLab) valueLab.layoutChain.rightToLeftOfView(arrow, offset: 6).centerY().leftToRightOfView(titleLab, offset: 12) case .avatar: addSubview(arrow) arrow.layoutChain.right(15).centerY().width(12).height(12) addSubview(avatar) avatar.layoutChain.rightToLeftOfView(arrow, offset: 8).centerY().width(28).height(28) if let pic = row.avatarURL, !pic.isEmpty, let img = UIImage(named: "UserIcon/\(pic)") { avatar.image = img } else if let urlStr = row.avatarURL, let u = URL(string: urlStr), urlStr.hasPrefix("http") { avatar.kf.setImage(with: u, placeholder: UIImage(named: "Common/default_avatar")) } else { avatar.image = UIImage(named: "Common/default_avatar") } case .tag: addSubview(tagLab) tagLab.layoutChain.right(15).centerY().height(20) tagLab.setContentHuggingPriority(.required, for: .horizontal) let pad = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10) tagLab.layoutMargins = pad // approximate width from text let w = (row.value as NSString).size(withAttributes: [.font: tagLab.font!]).width + 20 tagLab.layoutChain.width(max(60, w)) } if row.action != nil { addTarget(self, action: #selector(tap), for: .touchUpInside) } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @objc private func tap() { actionHandler?() } }