267 lines
8.2 KiB
Swift
267 lines
8.2 KiB
Swift
//
|
||
// 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
|
||
}()
|
||
}
|