851 lines
36 KiB
Swift
851 lines
36 KiB
Swift
//
|
|
// GroupSettingView.swift
|
|
// QuickLocation
|
|
//
|
|
// Created by 八条 on 2026/6/9.
|
|
//
|
|
|
|
import UIKit
|
|
import RxSwift
|
|
import RxCocoa
|
|
import TagListView
|
|
|
|
final class GroupSettingView: UIView {
|
|
|
|
private let pageInset: CGFloat = 15
|
|
var onRemoveMemberShortcutTapped: (() -> Void)?
|
|
var onMembersTapped: (() -> Void)?
|
|
|
|
func setupData(_ model: GroupInfoModel,
|
|
members: [GroupMemberModel],
|
|
groupNickname: String) {
|
|
groupNameView.setValue(model.name)
|
|
groupTypeView.setValue(model.groupTemplateName)
|
|
groupDescView.setValue(model.description.isEmpty ? "暂无描述" : model.description)
|
|
groupNicknameView.setValue(groupNickname)
|
|
tagView.configure(tags: model.labels, editable: model.is_owner)
|
|
|
|
switchBtn.isOn = model.review
|
|
auditSwitchView.isHidden = !model.is_owner
|
|
auditMemberView.isHidden = !model.is_owner
|
|
dismissGroupView.isHidden = !model.is_owner
|
|
leaveGroupView.isHidden = model.is_owner
|
|
|
|
groupNameView.setShowsArrow(model.is_owner)
|
|
groupTypeView.setShowsArrow(false)
|
|
groupDescView.setShowsArrow(model.is_owner)
|
|
groupNicknameView.setShowsArrow(true)
|
|
auditMemberView.setShowsArrow(model.is_owner)
|
|
|
|
let total = model.people_no > 0 ? model.people_no : members.count
|
|
let online = members.filter(\.is_online).count
|
|
memberCountLab.text = "共\(total)人/\(online)人在线"
|
|
memberGridView.configure(members: members, showsRemoveShortcut: model.is_owner)
|
|
setNeedsLayout()
|
|
}
|
|
|
|
func updateGroupNickname(_ nickname: String) {
|
|
groupNicknameView.setValue(nickname)
|
|
}
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = UIColor(hexStr: "#F7F8FA")
|
|
memberGridView.onRemoveMemberShortcutTapped = { [weak self] in
|
|
self?.onRemoveMemberShortcutTapped?()
|
|
}
|
|
memberGridView.onMembersTapped = { [weak self] in
|
|
self?.onMembersTapped?()
|
|
}
|
|
setupUI()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private func setupUI() {
|
|
addSubview(navBgView)
|
|
addSubview(navView)
|
|
addSubview(scrollView)
|
|
|
|
scrollView.addSubview(scrollContentView)
|
|
scrollContentView.addSubview(contentStackView)
|
|
|
|
contentStackView.addArrangedSubview(memberCardView)
|
|
contentStackView.addArrangedSubview(infoCardView)
|
|
contentStackView.addArrangedSubview(utilityCardView)
|
|
contentStackView.addArrangedSubview(dangerCardView)
|
|
|
|
setupMemberCard()
|
|
setupInfoCard()
|
|
setupUtilityCard()
|
|
setupDangerCard()
|
|
|
|
navBgView.translatesAutoresizingMaskIntoConstraints = false
|
|
navView.translatesAutoresizingMaskIntoConstraints = false
|
|
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
|
scrollContentView.translatesAutoresizingMaskIntoConstraints = false
|
|
contentStackView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
NSLayoutConstraint.activate([
|
|
navBgView.topAnchor.constraint(equalTo: topAnchor),
|
|
navBgView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
navBgView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
navBgView.heightAnchor.constraint(equalTo: widthAnchor, multiplier: 160.0 / 375.0),
|
|
|
|
navView.topAnchor.constraint(equalTo: topAnchor),
|
|
navView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
navView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
navView.heightAnchor.constraint(equalToConstant: kNaviHeight),
|
|
|
|
scrollView.topAnchor.constraint(equalTo: navView.bottomAnchor),
|
|
scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
|
|
scrollContentView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
|
|
scrollContentView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
|
|
scrollContentView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
|
|
scrollContentView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
|
|
scrollContentView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
|
|
|
|
contentStackView.topAnchor.constraint(equalTo: scrollContentView.topAnchor, constant: 14),
|
|
contentStackView.leadingAnchor.constraint(equalTo: scrollContentView.leadingAnchor, constant: pageInset),
|
|
contentStackView.trailingAnchor.constraint(equalTo: scrollContentView.trailingAnchor, constant: -pageInset),
|
|
contentStackView.bottomAnchor.constraint(equalTo: scrollContentView.bottomAnchor, constant: -30)
|
|
])
|
|
}
|
|
|
|
private func setupMemberCard() {
|
|
memberCardView.addSubview(memberHeaderView)
|
|
memberCardView.addSubview(memberGridView)
|
|
memberCardView.addSubview(memberSeparatorView)
|
|
memberCardView.addSubview(memberActionsView)
|
|
|
|
memberHeaderView.addSubview(memberTitleLab)
|
|
memberHeaderView.addSubview(memberCountLab)
|
|
memberHeaderView.addSubview(memberHeaderArrowView)
|
|
|
|
memberActionsView.addSubview(inviteCodeButton)
|
|
memberActionsView.addSubview(actionDividerView)
|
|
memberActionsView.addSubview(shareButton)
|
|
|
|
let views = [memberHeaderView, memberGridView, memberSeparatorView, memberActionsView,
|
|
memberTitleLab, memberCountLab, memberHeaderArrowView,
|
|
inviteCodeButton, actionDividerView, shareButton]
|
|
views.forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
|
|
|
|
NSLayoutConstraint.activate([
|
|
memberHeaderView.topAnchor.constraint(equalTo: memberCardView.topAnchor),
|
|
memberHeaderView.leadingAnchor.constraint(equalTo: memberCardView.leadingAnchor),
|
|
memberHeaderView.trailingAnchor.constraint(equalTo: memberCardView.trailingAnchor),
|
|
memberHeaderView.heightAnchor.constraint(equalToConstant: 44),
|
|
|
|
memberTitleLab.leadingAnchor.constraint(equalTo: memberHeaderView.leadingAnchor, constant: 16),
|
|
memberTitleLab.centerYAnchor.constraint(equalTo: memberHeaderView.centerYAnchor),
|
|
memberCountLab.trailingAnchor.constraint(equalTo: memberHeaderArrowView.leadingAnchor, constant: -8),
|
|
memberCountLab.centerYAnchor.constraint(equalTo: memberHeaderView.centerYAnchor),
|
|
memberHeaderArrowView.trailingAnchor.constraint(equalTo: memberHeaderView.trailingAnchor, constant: -16),
|
|
memberHeaderArrowView.centerYAnchor.constraint(equalTo: memberHeaderView.centerYAnchor),
|
|
memberHeaderArrowView.widthAnchor.constraint(equalToConstant: 16),
|
|
memberHeaderArrowView.heightAnchor.constraint(equalToConstant: 16),
|
|
|
|
memberGridView.topAnchor.constraint(equalTo: memberHeaderView.bottomAnchor),
|
|
memberGridView.leadingAnchor.constraint(equalTo: memberCardView.leadingAnchor, constant: 20),
|
|
memberGridView.trailingAnchor.constraint(equalTo: memberCardView.trailingAnchor, constant: -20),
|
|
|
|
memberSeparatorView.topAnchor.constraint(equalTo: memberGridView.bottomAnchor, constant: 6),
|
|
memberSeparatorView.leadingAnchor.constraint(equalTo: memberCardView.leadingAnchor, constant: 16),
|
|
memberSeparatorView.trailingAnchor.constraint(equalTo: memberCardView.trailingAnchor, constant: -16),
|
|
memberSeparatorView.heightAnchor.constraint(equalToConstant: 1),
|
|
|
|
memberActionsView.topAnchor.constraint(equalTo: memberSeparatorView.bottomAnchor, constant: 4),
|
|
memberActionsView.leadingAnchor.constraint(equalTo: memberCardView.leadingAnchor),
|
|
memberActionsView.trailingAnchor.constraint(equalTo: memberCardView.trailingAnchor),
|
|
memberActionsView.bottomAnchor.constraint(equalTo: memberCardView.bottomAnchor, constant: -6),
|
|
memberActionsView.heightAnchor.constraint(equalToConstant: 40),
|
|
|
|
inviteCodeButton.leadingAnchor.constraint(equalTo: memberActionsView.leadingAnchor),
|
|
inviteCodeButton.topAnchor.constraint(equalTo: memberActionsView.topAnchor),
|
|
inviteCodeButton.bottomAnchor.constraint(equalTo: memberActionsView.bottomAnchor),
|
|
inviteCodeButton.trailingAnchor.constraint(equalTo: actionDividerView.leadingAnchor),
|
|
|
|
actionDividerView.centerXAnchor.constraint(equalTo: memberActionsView.centerXAnchor),
|
|
actionDividerView.centerYAnchor.constraint(equalTo: memberActionsView.centerYAnchor),
|
|
actionDividerView.widthAnchor.constraint(equalToConstant: 0.5),
|
|
actionDividerView.heightAnchor.constraint(equalToConstant: 20),
|
|
|
|
shareButton.leadingAnchor.constraint(equalTo: actionDividerView.trailingAnchor),
|
|
shareButton.trailingAnchor.constraint(equalTo: memberActionsView.trailingAnchor),
|
|
shareButton.topAnchor.constraint(equalTo: memberActionsView.topAnchor),
|
|
shareButton.bottomAnchor.constraint(equalTo: memberActionsView.bottomAnchor)
|
|
])
|
|
}
|
|
|
|
private func setupInfoCard() {
|
|
infoCardView.addSubview(infoStackView)
|
|
infoStackView.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate([
|
|
infoStackView.topAnchor.constraint(equalTo: infoCardView.topAnchor),
|
|
infoStackView.leadingAnchor.constraint(equalTo: infoCardView.leadingAnchor),
|
|
infoStackView.trailingAnchor.constraint(equalTo: infoCardView.trailingAnchor),
|
|
infoStackView.bottomAnchor.constraint(equalTo: infoCardView.bottomAnchor)
|
|
])
|
|
|
|
infoStackView.addArrangedSubview(groupNameView)
|
|
infoStackView.addArrangedSubview(groupTypeView)
|
|
infoStackView.addArrangedSubview(groupDescView)
|
|
infoStackView.addArrangedSubview(groupNicknameView)
|
|
infoStackView.addArrangedSubview(auditSwitchView)
|
|
infoStackView.addArrangedSubview(auditMemberView)
|
|
infoStackView.addArrangedSubview(tagView)
|
|
}
|
|
|
|
private func setupUtilityCard() {
|
|
utilityCardView.addSubview(clearHistoryView)
|
|
clearHistoryView.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate(clearHistoryView.edgesToSuperview())
|
|
}
|
|
|
|
private func setupDangerCard() {
|
|
dangerCardView.addSubview(dangerStackView)
|
|
dangerStackView.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate(dangerStackView.edgesToSuperview())
|
|
dangerStackView.addArrangedSubview(dismissGroupView)
|
|
dangerStackView.addArrangedSubview(leaveGroupView)
|
|
}
|
|
|
|
private func makeMemberActionButton(title: String, imageName: String) -> UIButton {
|
|
let button = UIButton(type: .custom)
|
|
let stackView = UIStackView()
|
|
stackView.axis = .horizontal
|
|
stackView.alignment = .center
|
|
stackView.spacing = 7
|
|
stackView.isUserInteractionEnabled = false
|
|
|
|
let imageView = UIImageView(image: UIImage(named: imageName))
|
|
imageView.contentMode = .scaleAspectFit
|
|
imageView.widthAnchor.constraint(equalToConstant: 18).isActive = true
|
|
imageView.heightAnchor.constraint(equalToConstant: 18).isActive = true
|
|
|
|
let titleLab = UILabel()
|
|
titleLab.text = title
|
|
titleLab.textColor = UIColor(hexStr: "#293445")
|
|
titleLab.font = .systemFont(ofSize: 16, weight: .medium)
|
|
|
|
stackView.addArrangedSubview(imageView)
|
|
stackView.addArrangedSubview(titleLab)
|
|
button.addSubview(stackView)
|
|
stackView.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate([
|
|
stackView.centerXAnchor.constraint(equalTo: button.centerXAnchor),
|
|
stackView.centerYAnchor.constraint(equalTo: button.centerYAnchor)
|
|
])
|
|
return button
|
|
}
|
|
|
|
lazy var navBgView: UIImageView = {
|
|
let view = UIImageView(image: UIImage(named: "Common/navBar_bg_2"))
|
|
view.contentMode = .scaleAspectFill
|
|
return view
|
|
}()
|
|
|
|
lazy var navView: BaseNavigationView = BaseNavigationView(title: "圈子详情")
|
|
|
|
private lazy var scrollView: UIScrollView = {
|
|
let view = UIScrollView()
|
|
view.backgroundColor = .clear
|
|
view.showsVerticalScrollIndicator = false
|
|
return view
|
|
}()
|
|
|
|
private lazy var scrollContentView = UIView()
|
|
|
|
private lazy var contentStackView: UIStackView = {
|
|
let view = UIStackView()
|
|
view.axis = .vertical
|
|
view.spacing = 16
|
|
view.alignment = .fill
|
|
view.distribution = .fill
|
|
return view
|
|
}()
|
|
|
|
// MARK: - 圈子成员
|
|
private lazy var memberCardView = makeCardView()
|
|
|
|
let memberHeaderView = UIView()
|
|
|
|
private lazy var memberTitleLab: UILabel = {
|
|
let label = UILabel()
|
|
label.text = "圈子成员"
|
|
label.textColor = UIColor(hexStr: "#293445")
|
|
label.font = .systemFont(ofSize: 17, weight: .semibold)
|
|
return label
|
|
}()
|
|
|
|
private lazy var memberCountLab: UILabel = {
|
|
let label = UILabel()
|
|
label.textColor = UIColor(hexStr: "#A5A8AE")
|
|
label.font = .systemFont(ofSize: 13, weight: .regular)
|
|
return label
|
|
}()
|
|
|
|
private lazy var memberHeaderArrowView: UIImageView = makeArrowView()
|
|
|
|
private let memberGridView = GroupSettingMemberGridView()
|
|
private let memberSeparatorView = HorizontalDashLineView()
|
|
private let memberActionsView = UIView()
|
|
|
|
lazy var inviteCodeButton: UIButton = makeMemberActionButton(title: "邀请码", imageName: "GroupSetting/invite_code")
|
|
lazy var shareButton: UIButton = makeMemberActionButton(title: "分享", imageName: "GroupSetting/share")
|
|
|
|
private lazy var actionDividerView: UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = UIColor(hexStr: "#E7E8EA")
|
|
return view
|
|
}()
|
|
|
|
// MARK: - 圈子信息
|
|
private lazy var infoCardView = makeCardView()
|
|
|
|
private lazy var infoStackView: UIStackView = {
|
|
let view = UIStackView()
|
|
view.axis = .vertical
|
|
view.spacing = 0
|
|
view.alignment = .fill
|
|
view.distribution = .fill
|
|
return view
|
|
}()
|
|
|
|
let groupNameView = GroupSettingInfoRow(title: "圈子昵称", style: .text)
|
|
let groupTypeView = GroupSettingInfoRow(title: "圈子类型", style: .text)
|
|
let groupDescView = GroupSettingInfoRow(title: "圈子描述", style: .multilineText)
|
|
let groupNicknameView = GroupSettingInfoRow(title: "我在本群昵称", style: .text)
|
|
let auditSwitchView = GroupSettingInfoRow(title: "审核开关", style: .toggle)
|
|
let auditMemberView = GroupSettingInfoRow(title: "审核成员", style: .text)
|
|
let tagView = GroupSettingTagRow()
|
|
|
|
var switchBtn: UISwitch { auditSwitchView.switchButton }
|
|
|
|
// MARK: - 操作
|
|
private lazy var utilityCardView = makeCardView()
|
|
let clearHistoryView = GroupSettingActionRow(title: "清空聊天记录")
|
|
|
|
private lazy var dangerCardView = makeCardView()
|
|
|
|
private lazy var dangerStackView: UIStackView = {
|
|
let view = UIStackView()
|
|
view.axis = .vertical
|
|
view.spacing = 0
|
|
view.alignment = .fill
|
|
view.distribution = .fill
|
|
return view
|
|
}()
|
|
|
|
let dismissGroupView = GroupSettingActionRow(title: "解散圈子", titleColor: UIColor(hexStr: "#FF4D53"), hidesDivider: true)
|
|
let leaveGroupView = GroupSettingActionRow(title: "退出圈子", titleColor: UIColor(hexStr: "#FF4D53"), hidesDivider: true)
|
|
|
|
private func makeCardView() -> UIView {
|
|
let view = UIView()
|
|
view.backgroundColor = .white
|
|
view.layer.cornerRadius = 12
|
|
view.clipsToBounds = true
|
|
return view
|
|
}
|
|
|
|
private func makeArrowView() -> UIImageView {
|
|
let view = UIImageView(image: UIImage(named: "GroupSetting/arrow_right"))
|
|
view.contentMode = .scaleAspectFit
|
|
return view
|
|
}
|
|
}
|
|
|
|
private final class GroupSettingMemberGridView: UIView {
|
|
|
|
private let itemWidth: CGFloat = 56
|
|
private let itemHeight: CGFloat = 62
|
|
var onRemoveMemberShortcutTapped: (() -> Void)?
|
|
var onMembersTapped: (() -> Void)?
|
|
private weak var removeMemberCell: GroupSettingRemoveMemberCell?
|
|
|
|
private lazy var scrollView: UIScrollView = {
|
|
let view = UIScrollView()
|
|
view.showsHorizontalScrollIndicator = false
|
|
view.showsVerticalScrollIndicator = false
|
|
view.alwaysBounceHorizontal = true
|
|
view.delaysContentTouches = false
|
|
return view
|
|
}()
|
|
|
|
private lazy var itemsStackView: UIStackView = {
|
|
let view = UIStackView()
|
|
view.axis = .horizontal
|
|
view.spacing = 12
|
|
view.alignment = .top
|
|
view.distribution = .fill
|
|
return view
|
|
}()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
addSubview(scrollView)
|
|
scrollView.addSubview(itemsStackView)
|
|
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
|
|
tap.cancelsTouchesInView = false
|
|
scrollView.addGestureRecognizer(tap)
|
|
|
|
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
|
itemsStackView.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate([
|
|
scrollView.topAnchor.constraint(equalTo: topAnchor),
|
|
scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
|
|
itemsStackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
|
|
itemsStackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
|
|
itemsStackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
|
|
itemsStackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
|
|
itemsStackView.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor)
|
|
])
|
|
heightAnchor.constraint(equalToConstant: itemHeight).isActive = true
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func configure(members: [GroupMemberModel], showsRemoveShortcut: Bool) {
|
|
itemsStackView.arrangedSubviews.forEach {
|
|
itemsStackView.removeArrangedSubview($0)
|
|
$0.removeFromSuperview()
|
|
}
|
|
removeMemberCell = nil
|
|
|
|
members.forEach { member in
|
|
let cell = GroupSettingMemberCell(member: member)
|
|
cell.widthAnchor.constraint(equalToConstant: itemWidth).isActive = true
|
|
itemsStackView.addArrangedSubview(cell)
|
|
}
|
|
|
|
if showsRemoveShortcut {
|
|
let removeCell = GroupSettingRemoveMemberCell()
|
|
removeMemberCell = removeCell
|
|
removeCell.widthAnchor.constraint(equalToConstant: itemWidth).isActive = true
|
|
itemsStackView.addArrangedSubview(removeCell)
|
|
}
|
|
}
|
|
|
|
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
|
|
if let removeMemberCell {
|
|
let point = gesture.location(in: removeMemberCell)
|
|
if removeMemberCell.bounds.contains(point) {
|
|
onRemoveMemberShortcutTapped?()
|
|
return
|
|
}
|
|
}
|
|
onMembersTapped?()
|
|
}
|
|
}
|
|
|
|
private final class GroupSettingMemberCell: UIView {
|
|
|
|
init(member: GroupMemberModel) {
|
|
super.init(frame: .zero)
|
|
setupUI()
|
|
avatarView.image = member.userIcon
|
|
nicknameLab.text = member.nick_name.isEmpty ? "未知昵称" : member.nick_name
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private func setupUI() {
|
|
addSubview(avatarView)
|
|
addSubview(nicknameLab)
|
|
avatarView.translatesAutoresizingMaskIntoConstraints = false
|
|
nicknameLab.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate([
|
|
avatarView.topAnchor.constraint(equalTo: topAnchor),
|
|
avatarView.centerXAnchor.constraint(equalTo: centerXAnchor),
|
|
avatarView.widthAnchor.constraint(equalToConstant: 40),
|
|
avatarView.heightAnchor.constraint(equalToConstant: 40),
|
|
nicknameLab.topAnchor.constraint(equalTo: avatarView.bottomAnchor, constant: 5),
|
|
nicknameLab.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
nicknameLab.trailingAnchor.constraint(equalTo: trailingAnchor)
|
|
])
|
|
}
|
|
|
|
private lazy var avatarView: UIImageView = {
|
|
let view = UIImageView()
|
|
view.contentMode = .scaleAspectFill
|
|
view.layer.cornerRadius = 11
|
|
view.clipsToBounds = true
|
|
return view
|
|
}()
|
|
|
|
private lazy var nicknameLab: UILabel = {
|
|
let label = UILabel()
|
|
label.textColor = UIColor(hexStr: "#81858C")
|
|
label.font = .systemFont(ofSize: 11, weight: .regular)
|
|
label.textAlignment = .center
|
|
label.lineBreakMode = .byTruncatingTail
|
|
return label
|
|
}()
|
|
}
|
|
|
|
private final class GroupSettingRemoveMemberCell: UIView {
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
addSubview(iconContainer)
|
|
addSubview(titleLab)
|
|
iconContainer.addSubview(iconView)
|
|
[iconContainer, titleLab, iconView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
|
|
NSLayoutConstraint.activate([
|
|
iconContainer.topAnchor.constraint(equalTo: topAnchor),
|
|
iconContainer.centerXAnchor.constraint(equalTo: centerXAnchor),
|
|
iconContainer.widthAnchor.constraint(equalToConstant: 40),
|
|
iconContainer.heightAnchor.constraint(equalToConstant: 40),
|
|
iconView.centerXAnchor.constraint(equalTo: iconContainer.centerXAnchor),
|
|
iconView.centerYAnchor.constraint(equalTo: iconContainer.centerYAnchor),
|
|
iconView.widthAnchor.constraint(equalToConstant: 16),
|
|
iconView.heightAnchor.constraint(equalToConstant: 16),
|
|
titleLab.topAnchor.constraint(equalTo: iconContainer.bottomAnchor, constant: 5),
|
|
titleLab.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
titleLab.trailingAnchor.constraint(equalTo: trailingAnchor)
|
|
])
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private lazy var iconContainer: UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = UIColor(hexStr: "#F6F4F5")
|
|
view.layer.cornerRadius = 12
|
|
return view
|
|
}()
|
|
|
|
private lazy var iconView: UIImageView = {
|
|
let view = UIImageView(image: UIImage(named: "GroupSetting/remove_member"))
|
|
view.contentMode = .scaleAspectFit
|
|
return view
|
|
}()
|
|
|
|
private lazy var titleLab: UILabel = {
|
|
let label = UILabel()
|
|
label.text = "移除"
|
|
label.textColor = UIColor(hexStr: "#81858C")
|
|
label.font = .systemFont(ofSize: 11, weight: .regular)
|
|
label.textAlignment = .center
|
|
return label
|
|
}()
|
|
}
|
|
|
|
final class GroupSettingInfoRow: UIView {
|
|
|
|
enum Style {
|
|
case text
|
|
case icon
|
|
case multilineText
|
|
case toggle
|
|
}
|
|
|
|
let switchButton = UISwitch()
|
|
|
|
private let style: Style
|
|
private let titleLab = UILabel()
|
|
private let valueLab = UILabel()
|
|
private let valueImageView = UIImageView()
|
|
private let arrowImageView = UIImageView(image: UIImage(named: "GroupSetting/arrow_right"))
|
|
private let dividerView = UIView()
|
|
|
|
private var valueTrailingToArrow: NSLayoutConstraint?
|
|
private var valueTrailingToRow: NSLayoutConstraint?
|
|
private var imageTrailingToArrow: NSLayoutConstraint?
|
|
private var imageTrailingToRow: NSLayoutConstraint?
|
|
|
|
init(title: String, style: Style) {
|
|
self.style = style
|
|
super.init(frame: .zero)
|
|
titleLab.text = title
|
|
setupUI()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func setValue(_ value: String) {
|
|
valueLab.text = value
|
|
}
|
|
|
|
func setImage(_ image: UIImage?) {
|
|
valueImageView.image = image
|
|
}
|
|
|
|
func setShowsArrow(_ showsArrow: Bool) {
|
|
guard style != .toggle else { return }
|
|
arrowImageView.isHidden = !showsArrow
|
|
valueTrailingToArrow?.isActive = showsArrow
|
|
valueTrailingToRow?.isActive = !showsArrow
|
|
imageTrailingToArrow?.isActive = showsArrow
|
|
imageTrailingToRow?.isActive = !showsArrow
|
|
}
|
|
|
|
private func setupUI() {
|
|
backgroundColor = .clear
|
|
titleLab.textColor = UIColor(hexStr: "#293445")
|
|
titleLab.font = .systemFont(ofSize: 16, weight: .regular)
|
|
titleLab.setContentHuggingPriority(.required, for: .horizontal)
|
|
titleLab.setContentCompressionResistancePriority(.required, for: .horizontal)
|
|
valueLab.textColor = UIColor(hexStr: "#4B5565")
|
|
valueLab.font = .systemFont(ofSize: 16, weight: .regular)
|
|
valueLab.textAlignment = .right
|
|
valueLab.lineBreakMode = .byTruncatingTail
|
|
valueLab.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
|
valueImageView.contentMode = .scaleAspectFill
|
|
valueImageView.layer.cornerRadius = 10
|
|
valueImageView.clipsToBounds = true
|
|
arrowImageView.contentMode = .scaleAspectFit
|
|
dividerView.backgroundColor = UIColor(hexStr: "#EDEEF0")
|
|
switchButton.onTintColor = UIColor(hexStr: "#16B3FF")
|
|
|
|
[titleLab, valueLab, valueImageView, arrowImageView, switchButton, dividerView].forEach {
|
|
addSubview($0)
|
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
}
|
|
|
|
NSLayoutConstraint.activate([
|
|
titleLab.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
|
arrowImageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
arrowImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
arrowImageView.widthAnchor.constraint(equalToConstant: 16),
|
|
arrowImageView.heightAnchor.constraint(equalToConstant: 16),
|
|
dividerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
|
dividerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
dividerView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
dividerView.heightAnchor.constraint(equalToConstant: 0.5)
|
|
])
|
|
|
|
switch style {
|
|
case .text:
|
|
setupTextLayout(multiline: false)
|
|
case .icon:
|
|
setupIconLayout()
|
|
case .multilineText:
|
|
setupTextLayout(multiline: true)
|
|
case .toggle:
|
|
setupToggleLayout()
|
|
}
|
|
}
|
|
|
|
private func setupTextLayout(multiline: Bool) {
|
|
valueImageView.isHidden = true
|
|
switchButton.isHidden = true
|
|
valueTrailingToArrow = valueLab.trailingAnchor.constraint(equalTo: arrowImageView.leadingAnchor, constant: -10)
|
|
valueTrailingToRow = valueLab.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16)
|
|
valueTrailingToRow?.isActive = true
|
|
arrowImageView.isHidden = true
|
|
|
|
if multiline {
|
|
valueLab.numberOfLines = 2
|
|
valueLab.textAlignment = .right
|
|
NSLayoutConstraint.activate([
|
|
titleLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
valueLab.leadingAnchor.constraint(equalTo: titleLab.trailingAnchor, constant: 20),
|
|
valueLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
valueLab.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: 12),
|
|
valueLab.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -12),
|
|
heightAnchor.constraint(greaterThanOrEqualToConstant: 72)
|
|
])
|
|
} else {
|
|
NSLayoutConstraint.activate([
|
|
titleLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
valueLab.leadingAnchor.constraint(greaterThanOrEqualTo: titleLab.trailingAnchor, constant: 20),
|
|
valueLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
heightAnchor.constraint(equalToConstant: 62)
|
|
])
|
|
}
|
|
}
|
|
|
|
private func setupIconLayout() {
|
|
valueLab.isHidden = true
|
|
switchButton.isHidden = true
|
|
arrowImageView.isHidden = true
|
|
imageTrailingToArrow = valueImageView.trailingAnchor.constraint(equalTo: arrowImageView.leadingAnchor, constant: -12)
|
|
imageTrailingToRow = valueImageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16)
|
|
imageTrailingToRow?.isActive = true
|
|
NSLayoutConstraint.activate([
|
|
titleLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
valueImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
valueImageView.widthAnchor.constraint(equalToConstant: 40),
|
|
valueImageView.heightAnchor.constraint(equalToConstant: 40),
|
|
heightAnchor.constraint(equalToConstant: 64)
|
|
])
|
|
}
|
|
|
|
private func setupToggleLayout() {
|
|
valueLab.isHidden = true
|
|
valueImageView.isHidden = true
|
|
arrowImageView.isHidden = true
|
|
NSLayoutConstraint.activate([
|
|
titleLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
switchButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
switchButton.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
heightAnchor.constraint(equalToConstant: 62)
|
|
])
|
|
}
|
|
}
|
|
|
|
final class GroupSettingTagRow: UIView {
|
|
|
|
private let titleLab = UILabel()
|
|
private let arrowImageView = UIImageView(image: UIImage(named: "GroupSetting/arrow_right"))
|
|
private let tagListView = TagListView()
|
|
private let dividerView = UIView()
|
|
|
|
private var tagTrailingToArrow: NSLayoutConstraint?
|
|
private var tagTrailingToRow: NSLayoutConstraint?
|
|
|
|
init() {
|
|
super.init(frame: .zero)
|
|
setupUI()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func configure(tags: [String], editable: Bool) {
|
|
tagListView.removeAllTags()
|
|
tagListView.addTags(tags)
|
|
tagListView.tagViews.forEach { $0.layer.cornerRadius = 7 }
|
|
arrowImageView.isHidden = !editable
|
|
tagTrailingToArrow?.isActive = editable
|
|
tagTrailingToRow?.isActive = !editable
|
|
tagListView.invalidateIntrinsicContentSize()
|
|
}
|
|
|
|
private func setupUI() {
|
|
titleLab.text = "圈子标签"
|
|
titleLab.textColor = UIColor(hexStr: "#293445")
|
|
titleLab.font = .systemFont(ofSize: 16, weight: .regular)
|
|
titleLab.setContentHuggingPriority(.required, for: .horizontal)
|
|
titleLab.setContentCompressionResistancePriority(.required, for: .horizontal)
|
|
arrowImageView.contentMode = .scaleAspectFit
|
|
arrowImageView.isHidden = true
|
|
dividerView.backgroundColor = UIColor(hexStr: "#EDEEF0")
|
|
|
|
tagListView.textFont = .systemFont(ofSize: 14, weight: .regular)
|
|
tagListView.textColor = UIColor(hexStr: "#16B3FF")
|
|
tagListView.tagBackgroundColor = UIColor(hexStr: "#E4F6FF")
|
|
tagListView.paddingX = 12
|
|
tagListView.paddingY = 5
|
|
tagListView.alignment = .right
|
|
tagListView.setContentHuggingPriority(.defaultLow, for: .horizontal)
|
|
tagListView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
|
|
|
[titleLab, arrowImageView, tagListView, dividerView].forEach {
|
|
addSubview($0)
|
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
}
|
|
|
|
tagTrailingToArrow = tagListView.trailingAnchor.constraint(equalTo: arrowImageView.leadingAnchor, constant: -10)
|
|
tagTrailingToRow = tagListView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16)
|
|
tagTrailingToRow?.isActive = true
|
|
|
|
NSLayoutConstraint.activate([
|
|
titleLab.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
|
titleLab.topAnchor.constraint(equalTo: topAnchor, constant: 18),
|
|
arrowImageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
arrowImageView.centerYAnchor.constraint(equalTo: titleLab.centerYAnchor),
|
|
arrowImageView.widthAnchor.constraint(equalToConstant: 16),
|
|
arrowImageView.heightAnchor.constraint(equalToConstant: 16),
|
|
tagListView.leadingAnchor.constraint(equalTo: titleLab.trailingAnchor, constant: 20),
|
|
tagListView.topAnchor.constraint(equalTo: topAnchor, constant: 12),
|
|
tagListView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12),
|
|
tagListView.heightAnchor.constraint(greaterThanOrEqualToConstant: 28),
|
|
heightAnchor.constraint(greaterThanOrEqualToConstant: 62),
|
|
dividerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
|
dividerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
dividerView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
dividerView.heightAnchor.constraint(equalToConstant: 0.5)
|
|
])
|
|
}
|
|
}
|
|
|
|
final class GroupSettingActionRow: UIView {
|
|
|
|
init(title: String,
|
|
titleColor: UIColor = UIColor(hexStr: "#293445"),
|
|
hidesDivider: Bool = false) {
|
|
super.init(frame: .zero)
|
|
titleLab.text = title
|
|
titleLab.textColor = titleColor
|
|
dividerView.isHidden = hidesDivider
|
|
setupUI()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private func setupUI() {
|
|
titleLab.font = .systemFont(ofSize: 16, weight: .regular)
|
|
arrowImageView.contentMode = .scaleAspectFit
|
|
dividerView.backgroundColor = UIColor(hexStr: "#EDEEF0")
|
|
[titleLab, arrowImageView, dividerView].forEach {
|
|
addSubview($0)
|
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
}
|
|
|
|
NSLayoutConstraint.activate([
|
|
titleLab.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
|
titleLab.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
arrowImageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
arrowImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
arrowImageView.widthAnchor.constraint(equalToConstant: 16),
|
|
arrowImageView.heightAnchor.constraint(equalToConstant: 16),
|
|
dividerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
|
dividerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
|
|
dividerView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
dividerView.heightAnchor.constraint(equalToConstant: 0.5),
|
|
heightAnchor.constraint(equalToConstant: 62)
|
|
])
|
|
}
|
|
|
|
private let titleLab = UILabel()
|
|
private let arrowImageView = UIImageView(image: UIImage(named: "GroupSetting/arrow_right"))
|
|
private let dividerView = UIView()
|
|
}
|
|
|
|
private final class GroupSettingDashedLineView: UIView {
|
|
|
|
override func draw(_ rect: CGRect) {
|
|
guard let context = UIGraphicsGetCurrentContext() else { return }
|
|
context.setStrokeColor(UIColor(hexStr: "#D8D8D8").cgColor)
|
|
context.setLineWidth(1 / UIScreen.main.scale)
|
|
context.setLineDash(phase: 0, lengths: [4, 4])
|
|
context.move(to: CGPoint(x: 0, y: rect.midY))
|
|
context.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
|
|
context.strokePath()
|
|
}
|
|
}
|
|
|
|
private extension UIView {
|
|
func edgesToSuperview() -> [NSLayoutConstraint] {
|
|
guard let superview = superview else { return [] }
|
|
return [
|
|
topAnchor.constraint(equalTo: superview.topAnchor),
|
|
leadingAnchor.constraint(equalTo: superview.leadingAnchor),
|
|
trailingAnchor.constraint(equalTo: superview.trailingAnchor),
|
|
bottomAnchor.constraint(equalTo: superview.bottomAnchor)
|
|
]
|
|
}
|
|
}
|