853 lines
27 KiB
Swift
853 lines
27 KiB
Swift
//
|
||
// LockDistractView.swift
|
||
// QuickLocation
|
||
//
|
||
|
||
import UIKit
|
||
import RxSwift
|
||
import RxCocoa
|
||
import Kingfisher
|
||
|
||
enum LockDistractPrimaryAction {
|
||
case lock
|
||
case requestUnlock
|
||
case unlock
|
||
case hidden
|
||
}
|
||
|
||
final class LockDistractView: UIView {
|
||
|
||
var disposeBag = DisposeBag()
|
||
|
||
let lockIconNames = [
|
||
"LockDistract/lock_icon_1",
|
||
"LockDistract/lock_icon_2",
|
||
"LockDistract/lock_icon_3",
|
||
"LockDistract/lock_icon_4",
|
||
"LockDistract/lock_icon_5",
|
||
"LockDistract/lock_icon_6",
|
||
"LockDistract/lock_icon_7"
|
||
]
|
||
|
||
private(set) var selectedLockIconIndex = 0
|
||
private(set) var selectedAppIndexes: Set<Int> = []
|
||
private(set) var lockableApps: [PhoneLockAppItem] = []
|
||
private(set) var isLocked = false
|
||
private(set) var isCurrentUser = false
|
||
private(set) var primaryAction: LockDistractPrimaryAction = .lock
|
||
private let copyMaxLength = 20
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: frame)
|
||
backgroundColor = UIColor(hexStr: "#FAFAFA")
|
||
setupUI()
|
||
setupCopyLimit()
|
||
applyLockedState()
|
||
}
|
||
|
||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||
|
||
func configureMember(
|
||
name: String,
|
||
avatar: UIImage? = nil,
|
||
headPic: String? = nil,
|
||
isCurrentUser: Bool = false
|
||
) {
|
||
self.isCurrentUser = isCurrentUser
|
||
memberNameLab.text = name.isEmpty ? " " : name
|
||
if let headPic, !headPic.isEmpty {
|
||
memberAvatar.setHeadPic(headPic)
|
||
} else {
|
||
memberAvatar.image = avatar ?? HeadPic.placeholder
|
||
}
|
||
updateLockedEmptyImage()
|
||
}
|
||
|
||
func setTodayLockCount(_ count: Int) {
|
||
todayCountLab.text = "\(count)"
|
||
}
|
||
|
||
func setGroupName(_ name: String) {
|
||
// let title = name.isEmpty ? "切换圈子" : " \(name) "
|
||
// switchGroupBtn.setTitle(title, for: .normal)
|
||
|
||
let trimmedName = name.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
var titleAttributes = AttributeContainer()
|
||
titleAttributes.font = .systemFont(ofSize: 12, weight: .medium)
|
||
|
||
var configuration = switchGroupBtn.configuration ?? UIButton.Configuration.plain()
|
||
configuration.attributedTitle = AttributedString(
|
||
trimmedName.isEmpty ? "当前圈子" : trimmedName,
|
||
attributes: titleAttributes
|
||
)
|
||
configuration.image = UIImage(named: "Home/group_name_icon")
|
||
configuration.imagePadding = 3
|
||
configuration.contentInsets = NSDirectionalEdgeInsets(
|
||
top: 0,
|
||
leading: 6,
|
||
bottom: 0,
|
||
trailing: 6
|
||
)
|
||
configuration.baseForegroundColor = UIColor(hexStr: "#293445")
|
||
switchGroupBtn.configuration = configuration
|
||
switchGroupBtn.titleLabel?.lineBreakMode = .byTruncatingTail
|
||
switchGroupBtn.sizeToFit()
|
||
}
|
||
|
||
func configureLocked(_ locked: Bool, action: LockDistractPrimaryAction? = nil) {
|
||
isLocked = locked
|
||
primaryAction = action ?? (locked ? .requestUnlock : .lock)
|
||
applyLockedState()
|
||
}
|
||
|
||
func configureLockableApps(_ apps: [PhoneLockAppItem]) {
|
||
lockableApps = apps
|
||
selectedAppIndexes.removeAll()
|
||
notFetchedView.isHidden = !apps.isEmpty
|
||
appCollectionView.reloadData()
|
||
}
|
||
|
||
var selectedLockApps: [PhoneLockAppItem] {
|
||
lockableApps.enumerated().compactMap { index, app in
|
||
selectedAppIndexes.contains(index) ? app : nil
|
||
}
|
||
}
|
||
|
||
var lockMessage: String {
|
||
(copyTF.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||
}
|
||
|
||
var onPrivilegeAction: (() -> Void)?
|
||
private(set) var isPrivilegeDenied = false
|
||
private let privilegeOverlay = PrivilegeDeniedOverlay()
|
||
|
||
func setPrivilegeDenied(_ denied: Bool, isCurrentUser: Bool) {
|
||
isPrivilegeDenied = denied
|
||
privilegeOverlay.configure(
|
||
title: "TA未开启权限",
|
||
message: "无法查看可锁应用",
|
||
actionTitle: isCurrentUser ? "去开启" : "提醒TA"
|
||
)
|
||
privilegeOverlay.onAction = { [weak self] in self?.onPrivilegeAction?() }
|
||
privilegeOverlay.setVisible(denied)
|
||
if denied {
|
||
contentView.bringSubviewToFront(privilegeOverlay)
|
||
}
|
||
}
|
||
|
||
private func applyLockedState() {
|
||
updateLockedEmptyImage()
|
||
avatarLockView.isHidden = !isLocked
|
||
styleSectionTitle.isHidden = isLocked
|
||
styleCard.isHidden = isLocked
|
||
lockedEmptyView.isHidden = !isLocked
|
||
appCollectionView.reloadData()
|
||
lockBtn.isHidden = primaryAction == .hidden
|
||
switch primaryAction {
|
||
case .lock:
|
||
tipLab.text = "锁定功能需要在对方开启权限情况下才能使用哟~"
|
||
lockBtn.setTitle("锁定", for: .normal)
|
||
case .requestUnlock:
|
||
tipLab.text = "已被其他圈主锁定,请先申请解锁哟~"
|
||
lockBtn.setTitle("请求解锁", for: .normal)
|
||
case .unlock:
|
||
tipLab.text = "TA已经被你锁定,解锁后才能重新设置哟~"
|
||
lockBtn.setTitle("解锁", for: .normal)
|
||
case .hidden:
|
||
tipLab.text = "该成员的APP已被其他圈主锁定~"
|
||
}
|
||
}
|
||
|
||
private func updateLockedEmptyImage() {
|
||
let imageName = isCurrentUser ? "LockDistract/locked_self" : "LockDistract/locked_empty"
|
||
lockedEmptyView.image = UIImage(named: imageName)
|
||
}
|
||
|
||
private func setupUI() {
|
||
addSubview(scrollView)
|
||
scrollView.addSubview(contentView)
|
||
addSubview(navView)
|
||
navView.addRightButton(switchGroupBtn)
|
||
addSubview(footerBar)
|
||
footerBar.addSubview(tipRow)
|
||
footerBar.addSubview(lockBtn)
|
||
|
||
contentView.addSubview(navBgView)
|
||
contentView.addSubview(statsRow)
|
||
statsRow.addArrangedSubview(memberCard)
|
||
statsRow.addArrangedSubview(todayCard)
|
||
contentView.addSubview(appsSectionTitle)
|
||
contentView.addSubview(appsCard)
|
||
appsCard.addSubview(appsHeaderRow)
|
||
appsCard.addSubview(appCollectionView)
|
||
contentView.addSubview(bottomStack)
|
||
bottomStack.addArrangedSubview(styleSectionTitle)
|
||
bottomStack.addArrangedSubview(styleCard)
|
||
bottomStack.addArrangedSubview(lockedEmptyView)
|
||
contentView.addSubview(privilegeOverlay)
|
||
|
||
navView.layoutChain
|
||
.edges(excludingEdge: .bottom)
|
||
.height(kNaviHeight)
|
||
|
||
footerBar.layoutChain
|
||
.edgesHorzontal()
|
||
.bottom()
|
||
|
||
lockBtn.layoutChain
|
||
.bottom(kSafeBottomMargin)
|
||
.edgesHorzontal(30)
|
||
.height(56)
|
||
|
||
tipRow.layoutChain
|
||
.centerX()
|
||
.bottomToTopOfView(lockBtn, offset: -8)
|
||
.top(10)
|
||
|
||
scrollView.layoutChain
|
||
.top()
|
||
.edgesHorzontal()
|
||
.bottomToTopOfView(footerBar)
|
||
|
||
contentView.layoutChain
|
||
.edges()
|
||
.widthToView(scrollView)
|
||
|
||
navBgView.layoutChain
|
||
.top()
|
||
.edgesHorzontal()
|
||
.heightToWidth(200.0 / 375.0)
|
||
|
||
statsRow.layoutChain
|
||
.topToBottomOfView(navBgView, offset: -48)
|
||
.edgesHorzontal(16)
|
||
.height(122)
|
||
|
||
appsSectionTitle.layoutChain
|
||
.topToBottomOfView(statsRow, offset: 14)
|
||
.left(20)
|
||
|
||
appsCard.layoutChain
|
||
.topToBottomOfView(appsSectionTitle, offset: 10)
|
||
.edgesHorzontal(16)
|
||
|
||
appsHeaderRow.layoutChain
|
||
.top(10)
|
||
.edgesHorzontal(18)
|
||
.height(17)
|
||
|
||
appCollectionView.layoutChain
|
||
.topToBottomOfView(appsHeaderRow, offset: 12)
|
||
.edgesHorzontal(8)
|
||
.height(78)
|
||
.bottom()
|
||
|
||
bottomStack.layoutChain
|
||
.topToBottomOfView(appsCard, offset: 11)
|
||
.edgesHorzontal(16)
|
||
.bottom(20)
|
||
|
||
privilegeOverlay.layoutChain
|
||
.topToView(appsSectionTitle)
|
||
.left(16)
|
||
.right(16)
|
||
.bottomToView(bottomStack)
|
||
privilegeOverlay.layer.cornerRadius = 26
|
||
|
||
styleSectionTitle.layoutChain.left(4)
|
||
lockedEmptyView.layoutChain
|
||
.centerX()
|
||
// .height(150)
|
||
}
|
||
|
||
private func setupCopyLimit() {
|
||
copyTF.rx.text.orEmpty
|
||
.subscribe(onNext: { [weak self] _ in
|
||
guard let self else { return }
|
||
guard let text = self.copyTF.limitCommittedText(to: self.copyMaxLength) else { return }
|
||
self.copyCountLab.text = "\(text.count)/\(self.copyMaxLength)"
|
||
})
|
||
.disposed(by: disposeBag)
|
||
}
|
||
|
||
// MARK: - Views
|
||
|
||
lazy var navBgView: UIImageView = {
|
||
let iv = UIImageView()
|
||
iv.image = UIImage(named: "LockDistract/header_hero")
|
||
iv.contentMode = .scaleAspectFill
|
||
iv.clipsToBounds = true
|
||
return iv
|
||
}()
|
||
|
||
lazy var navView: BaseNavigationView = {
|
||
BaseNavigationView(title: "")
|
||
}()
|
||
|
||
lazy var footerBar: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = UIColor(hexStr: "#FAFAFA")
|
||
return view
|
||
}()
|
||
|
||
lazy var switchGroupBtn: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.backgroundColor = .white.withAlphaComponent(0.92)
|
||
btn.setImage(UIImage(named: "Home/group_name_icon"), for: .normal)
|
||
btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium)
|
||
btn.setTitleColor(UIColor(hexStr: "#293445"), for: .normal)
|
||
btn.cornerRadius = 8
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 20, left: 12, bottom: 12, right: 4)
|
||
return btn
|
||
}()
|
||
|
||
lazy var scrollView: UIScrollView = {
|
||
let sv = UIScrollView()
|
||
sv.contentInsetAdjustmentBehavior = .never
|
||
sv.showsVerticalScrollIndicator = false
|
||
sv.keyboardDismissMode = .onDrag
|
||
return sv
|
||
}()
|
||
|
||
lazy var contentView = UIView()
|
||
|
||
lazy var statsRow: UIStackView = {
|
||
let stack = UIStackView()
|
||
stack.axis = .horizontal
|
||
stack.spacing = 12
|
||
stack.distribution = .fillEqually
|
||
return stack
|
||
}()
|
||
|
||
lazy var memberCard: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .white
|
||
view.cornerRadius = 16
|
||
|
||
view.addSubview(memberPrevBtn)
|
||
view.addSubview(memberAvatar)
|
||
view.addSubview(avatarLockView)
|
||
view.addSubview(memberNextBtn)
|
||
view.addSubview(memberNameChip)
|
||
memberNameChip.addSubview(memberNameLab)
|
||
|
||
memberAvatar.layoutChain
|
||
.top(18)
|
||
.centerX()
|
||
.width(56)
|
||
.height(56)
|
||
|
||
avatarLockView.layoutChain
|
||
.topToView(memberAvatar)
|
||
.leftToView(memberAvatar)
|
||
.rightToView(memberAvatar)
|
||
.bottomToView(memberAvatar)
|
||
|
||
memberPrevBtn.layoutChain
|
||
.centerY(memberAvatar)
|
||
.rightToLeftOfView(memberAvatar, offset: -18)
|
||
.width(16)
|
||
.height(16)
|
||
|
||
memberNextBtn.layoutChain
|
||
.centerY(memberAvatar)
|
||
.leftToRightOfView(memberAvatar, offset: 18)
|
||
.width(16)
|
||
.height(16)
|
||
|
||
memberNameChip.layoutChain
|
||
.topToBottomOfView(memberAvatar, offset: 10)
|
||
.centerX()
|
||
.left(8, relation: .greaterThanOrEqual)
|
||
.right(8, relation: .greaterThanOrEqual)
|
||
.bottom(14)
|
||
|
||
memberNameLab.layoutChain
|
||
.top(6)
|
||
.bottom(6)
|
||
.left(5)
|
||
.right(5)
|
||
|
||
return view
|
||
}()
|
||
|
||
lazy var memberAvatar: UIImageView = {
|
||
let iv = UIImageView(image: UIImage(named: "Common/default_avatar"))
|
||
iv.contentMode = .scaleAspectFill
|
||
iv.clipsToBounds = true
|
||
iv.cornerRadius = 12
|
||
return iv
|
||
}()
|
||
|
||
lazy var avatarLockView: UIImageView = {
|
||
let iv = UIImageView(image: UIImage(named: "LockDistract/avatar_lock"))
|
||
iv.contentMode = .scaleAspectFill
|
||
iv.clipsToBounds = true
|
||
iv.cornerRadius = 12
|
||
iv.isHidden = true
|
||
return iv
|
||
}()
|
||
|
||
lazy var memberNameChip: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = UIColor(hexStr: "#F2F2F2")
|
||
view.cornerRadius = 8
|
||
return view
|
||
}()
|
||
|
||
lazy var memberNameLab: UILabel = {
|
||
let lab = UILabel()
|
||
lab.text = " "
|
||
lab.font = .systemFont(ofSize: 10, weight: .bold)
|
||
lab.textColor = UIColor(hexStr: "#293445")
|
||
lab.textAlignment = .center
|
||
lab.lineBreakMode = .byTruncatingTail
|
||
return lab
|
||
}()
|
||
|
||
lazy var memberPrevBtn: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.setImage(UIImage(named: "LockDistract/member_prev"), for: .normal)
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 50, left: 30, bottom: 50, right: 18)
|
||
return btn
|
||
}()
|
||
|
||
lazy var memberNextBtn: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.setImage(UIImage(named: "LockDistract/member_next"), for: .normal)
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 50, left: 18, bottom: 50, right: 30)
|
||
return btn
|
||
}()
|
||
|
||
lazy var todayCard: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .white
|
||
view.cornerRadius = 16
|
||
|
||
let title = UILabel()
|
||
title.text = "今日锁定应用"
|
||
title.font = .systemFont(ofSize: 16, weight: .bold)
|
||
title.textColor = UIColor(hexStr: "#293445")
|
||
view.addSubview(title)
|
||
title.layoutChain.top(21).left(23)
|
||
|
||
view.addSubview(todayCountLab)
|
||
view.addSubview(todayUnitLab)
|
||
|
||
todayCountLab.layoutChain
|
||
.leftToView(title, offset: 4)
|
||
.bottom(10)
|
||
todayUnitLab.layoutChain
|
||
.leftToRightOfView(todayCountLab, offset: 7)
|
||
.bottomToView(todayCountLab, offset: -12)
|
||
|
||
return view
|
||
}()
|
||
|
||
lazy var todayCountLab: UILabel = {
|
||
let lab = UILabel()
|
||
lab.text = "0"
|
||
lab.font = .systemFont(ofSize: 50, weight: .heavy)
|
||
lab.textColor = UIColor(hexStr: "#00ADFE")
|
||
return lab
|
||
}()
|
||
|
||
lazy var todayUnitLab: UILabel = {
|
||
let lab = UILabel()
|
||
lab.text = "个"
|
||
lab.font = .systemFont(ofSize: 16, weight: .bold)
|
||
lab.textColor = UIColor(hexStr: "#293445")
|
||
return lab
|
||
}()
|
||
|
||
lazy var appsSectionTitle: UIView = {
|
||
makeSectionTitle("锁定应用")
|
||
}()
|
||
|
||
lazy var appsCard: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .white
|
||
view.cornerRadius = 26
|
||
return view
|
||
}()
|
||
|
||
lazy var appsHeaderRow: UIView = {
|
||
let row = UIView()
|
||
let left = UILabel()
|
||
left.text = "选择锁定TA的app"
|
||
left.font = .systemFont(ofSize: 14, weight: .medium)
|
||
left.textColor = UIColor(hexStr: "#293445")
|
||
row.addSubview(left)
|
||
left.layoutChain.left().centerY()
|
||
|
||
row.addSubview(notFetchedView)
|
||
notFetchedView.layoutChain.right().centerY().height(17)
|
||
row.layoutChain.height(17)
|
||
return row
|
||
}()
|
||
|
||
lazy var notFetchedView: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 4)
|
||
|
||
let warn = UIView()
|
||
warn.isUserInteractionEnabled = false
|
||
warn.backgroundColor = UIColor(hexStr: "#FA5151")
|
||
warn.cornerRadius = 5
|
||
let warnText = UILabel()
|
||
warnText.text = "!"
|
||
warnText.textColor = .white
|
||
warnText.font = .systemFont(ofSize: 8)
|
||
warnText.isUserInteractionEnabled = false
|
||
btn.addSubview(warn)
|
||
warn.addSubview(warnText)
|
||
warnText.layoutChain.centerX().centerY()
|
||
|
||
let notFetchedText = UILabel()
|
||
notFetchedText.text = "未获取"
|
||
notFetchedText.textColor = UIColor(hexStr: "#293445")
|
||
notFetchedText.font = .systemFont(ofSize: 12, weight: .medium)
|
||
notFetchedText.isUserInteractionEnabled = false
|
||
btn.addSubview(notFetchedText)
|
||
|
||
let arrow = UIImageView(image: UIImage(named: "LockDistract/arrow_right"))
|
||
arrow.isUserInteractionEnabled = false
|
||
btn.addSubview(arrow)
|
||
|
||
warn.layoutChain
|
||
.left()
|
||
.centerY()
|
||
.width(10).height(10)
|
||
|
||
notFetchedText.layoutChain
|
||
.leftToRightOfView(warn, offset: 4)
|
||
.centerY()
|
||
|
||
arrow.layoutChain
|
||
.leftToRightOfView(notFetchedText, offset: 2)
|
||
.right()
|
||
.width(10)
|
||
.heightToWidth(1)
|
||
.centerY()
|
||
|
||
return btn
|
||
}()
|
||
|
||
lazy var appCollectionView: UICollectionView = {
|
||
let layout = UICollectionViewFlowLayout()
|
||
layout.scrollDirection = .horizontal
|
||
layout.itemSize = CGSize(width: 56, height: 78)
|
||
layout.minimumLineSpacing = 12
|
||
layout.sectionInset = UIEdgeInsets(top: 0, left: 6, bottom: 0, right: 6)
|
||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||
cv.backgroundColor = .clear
|
||
cv.showsHorizontalScrollIndicator = false
|
||
cv.register(LockDistractAppCell.self)
|
||
cv.dataSource = self
|
||
cv.delegate = self
|
||
cv.tag = 1
|
||
return cv
|
||
}()
|
||
|
||
lazy var bottomStack: UIStackView = {
|
||
let stack = UIStackView()
|
||
stack.axis = .vertical
|
||
stack.alignment = .fill
|
||
stack.spacing = 10
|
||
return stack
|
||
}()
|
||
|
||
lazy var styleSectionTitle: UIView = {
|
||
makeSectionTitle("锁定界面样式")
|
||
}()
|
||
|
||
lazy var styleCard: UIView = {
|
||
let card = UIView()
|
||
card.backgroundColor = .white
|
||
card.cornerRadius = 26
|
||
|
||
let wallLab = UILabel()
|
||
wallLab.text = "锁定图标"
|
||
wallLab.font = .systemFont(ofSize: 13, weight: .medium)
|
||
wallLab.textColor = UIColor(hexStr: "#8A94A6")
|
||
card.addSubview(wallLab)
|
||
wallLab.layoutChain.top(12).left(18)
|
||
|
||
card.addSubview(lockIconCV)
|
||
lockIconCV.layoutChain
|
||
.topToBottomOfView(wallLab, offset: 10)
|
||
.edgesHorzontal(18)
|
||
.height(74)
|
||
|
||
let copyLab = UILabel()
|
||
copyLab.text = "锁定文案"
|
||
copyLab.font = .systemFont(ofSize: 13, weight: .medium)
|
||
copyLab.textColor = UIColor(hexStr: "#8A94A6")
|
||
card.addSubview(copyLab)
|
||
copyLab.layoutChain.topToBottomOfView(lockIconCV, offset: 16).left(18)
|
||
|
||
let input = UIView()
|
||
input.backgroundColor = UIColor(hexStr: "#F5F6F8")
|
||
input.cornerRadius = 12
|
||
card.addSubview(input)
|
||
input.layoutChain
|
||
.topToBottomOfView(copyLab, offset: 10)
|
||
.edgesHorzontal(18)
|
||
.height(44)
|
||
.bottom(16)
|
||
|
||
input.addSubview(copyTF)
|
||
input.addSubview(copyCountLab)
|
||
copyCountLab.layoutChain.centerY().right(12).width(35)
|
||
copyTF.layoutChain.edgesVertical().left(12).rightToLeftOfView(copyCountLab, offset: -8)
|
||
|
||
return card
|
||
}()
|
||
|
||
lazy var lockIconCV: UICollectionView = {
|
||
let layout = UICollectionViewFlowLayout()
|
||
layout.scrollDirection = .horizontal
|
||
layout.itemSize = CGSize(width: 56, height: 74)
|
||
layout.minimumLineSpacing = 10
|
||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||
cv.backgroundColor = .clear
|
||
cv.showsHorizontalScrollIndicator = false
|
||
cv.register(LockDistractWallpaperCell.self)
|
||
cv.dataSource = self
|
||
cv.delegate = self
|
||
cv.tag = 2
|
||
return cv
|
||
}()
|
||
|
||
lazy var copyTF: UITextField = {
|
||
let tf = UITextField()
|
||
tf.font = .systemFont(ofSize: 14, weight: .medium)
|
||
tf.textColor = UIColor(hexStr: "#293445")
|
||
tf.placeholderColor(placeholder: "随便说点什么吧~",
|
||
color: UIColor(hexStr: "#999999"),
|
||
font: .systemFont(ofSize: 14, weight: .medium))
|
||
return tf
|
||
}()
|
||
|
||
lazy var copyCountLab: UILabel = {
|
||
let lab = UILabel()
|
||
lab.text = "0/20"
|
||
lab.font = .systemFont(ofSize: 14, weight: .medium)
|
||
lab.textColor = UIColor(hexStr: "#AAAAAA")
|
||
return lab
|
||
}()
|
||
|
||
lazy var lockedEmptyView: UIImageView = {
|
||
let iv = UIImageView(image: UIImage(named: "LockDistract/locked_empty"))
|
||
iv.contentMode = .scaleAspectFit
|
||
iv.isHidden = true
|
||
return iv
|
||
}()
|
||
|
||
lazy var tipLab: UILabel = {
|
||
let lab = UILabel()
|
||
lab.text = "锁定功能只有在圈主的情况下才能使用哟~"
|
||
lab.font = .systemFont(ofSize: 12, weight: .regular)
|
||
lab.textColor = UIColor(hexStr: "#293445")
|
||
lab.numberOfLines = 0
|
||
return lab
|
||
}()
|
||
|
||
lazy var tipRow: UIView = {
|
||
let row = UIView()
|
||
let icon = UIImageView(image: UIImage(named: "LockDistract/info_circle"))
|
||
icon.contentMode = .scaleAspectFit
|
||
row.addSubview(icon)
|
||
row.addSubview(tipLab)
|
||
icon.layoutChain.left().centerY().width(14).height(14)
|
||
tipLab.layoutChain.leftToRightOfView(icon, offset: 6).right().top().bottom()
|
||
return row
|
||
}()
|
||
|
||
lazy var lockBtn: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.setTitle("锁定", for: .normal)
|
||
btn.setTitleColor(.white, for: .normal)
|
||
btn.titleLabel?.font = FontManager.boboBold(18)
|
||
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
|
||
btn.cornerRadius = 20
|
||
return btn
|
||
}()
|
||
|
||
private func makeSectionTitle(_ text: String) -> UIView {
|
||
let row = UIView()
|
||
let star = UIImageView(image: UIImage(named: "LockDistract/section_star"))
|
||
star.contentMode = .scaleAspectFit
|
||
let lab = UILabel()
|
||
lab.text = text
|
||
lab.font = .systemFont(ofSize: 16, weight: .bold)
|
||
lab.textColor = UIColor(hexStr: "#1F2A44")
|
||
row.addSubview(star)
|
||
row.addSubview(lab)
|
||
star.layoutChain.left().centerY().width(14).height(14)
|
||
lab.layoutChain.leftToRightOfView(star, offset: 6).right().centerY()
|
||
row.layoutChain.height(22)
|
||
return row
|
||
}
|
||
}
|
||
|
||
extension LockDistractView: UICollectionViewDataSource, UICollectionViewDelegate {
|
||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||
collectionView.tag == 1 ? max(lockableApps.count, 1) : lockIconNames.count
|
||
}
|
||
|
||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||
if collectionView.tag == 1 {
|
||
let cell = collectionView.dequeueReusableCell(for: indexPath) as LockDistractAppCell
|
||
let hasApps = !lockableApps.isEmpty
|
||
let iconURL = hasApps ? lockableApps[indexPath.item].icon : nil
|
||
let locked = hasApps && lockableApps[indexPath.item].locked
|
||
cell.configure(
|
||
iconURL: iconURL,
|
||
selected: selectedAppIndexes.contains(indexPath.item),
|
||
showsCheck: hasApps && !isLocked,
|
||
locked: locked
|
||
)
|
||
return cell
|
||
}
|
||
let cell = collectionView.dequeueReusableCell(for: indexPath) as LockDistractWallpaperCell
|
||
cell.configure(
|
||
imageName: lockIconNames[indexPath.item],
|
||
isSelected: indexPath.item == selectedLockIconIndex
|
||
)
|
||
return cell
|
||
}
|
||
|
||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||
if collectionView.tag == 1 {
|
||
guard !isLocked, !lockableApps.isEmpty, !lockableApps[indexPath.item].locked else { return }
|
||
if selectedAppIndexes.contains(indexPath.item) {
|
||
selectedAppIndexes.remove(indexPath.item)
|
||
} else {
|
||
selectedAppIndexes.insert(indexPath.item)
|
||
}
|
||
collectionView.reloadData()
|
||
return
|
||
}
|
||
selectedLockIconIndex = indexPath.item
|
||
collectionView.reloadData()
|
||
}
|
||
}
|
||
|
||
final class LockDistractAppCell: UICollectionViewCell {
|
||
private let iconView: UIImageView = {
|
||
let iv = UIImageView()
|
||
iv.contentMode = .scaleAspectFit
|
||
iv.clipsToBounds = true
|
||
iv.cornerRadius = 12
|
||
return iv
|
||
}()
|
||
|
||
private let checkBtn: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.setImage(UIImage(named: "Common/checkbox"), for: .normal)
|
||
btn.setImage(UIImage(named: "Common/checkbox_on"), for: .selected)
|
||
btn.isUserInteractionEnabled = false
|
||
return btn
|
||
}()
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: frame)
|
||
contentView.addSubview(iconView)
|
||
contentView.addSubview(lockDimView)
|
||
contentView.addSubview(lockIconView)
|
||
contentView.addSubview(checkBtn)
|
||
iconView.layoutChain.top().centerX().width(48).height(48)
|
||
lockDimView.layoutChain
|
||
.topToView(iconView)
|
||
.leftToView(iconView)
|
||
.rightToView(iconView)
|
||
.bottomToView(iconView)
|
||
lockIconView.layoutChain
|
||
.centerX(iconView)
|
||
.centerY(iconView)
|
||
.width(14)
|
||
.height(14)
|
||
checkBtn.layoutChain.topToBottomOfView(iconView, offset: 6).centerX().width(16).height(16)
|
||
}
|
||
|
||
private let lockDimView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = UIColor.black.withAlphaComponent(0.3)
|
||
view.layer.cornerRadius = 12
|
||
view.clipsToBounds = true
|
||
view.isHidden = true
|
||
view.isUserInteractionEnabled = false
|
||
return view
|
||
}()
|
||
|
||
private let lockIconView: UIImageView = {
|
||
let iv = UIImageView(image: UIImage(named: "LockDistract/app_list_lock"))
|
||
iv.contentMode = .scaleAspectFit
|
||
iv.isHidden = true
|
||
return iv
|
||
}()
|
||
|
||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||
|
||
override func prepareForReuse() {
|
||
super.prepareForReuse()
|
||
iconView.kf.cancelDownloadTask()
|
||
iconView.image = nil
|
||
lockDimView.isHidden = true
|
||
lockIconView.isHidden = true
|
||
}
|
||
|
||
func configure(iconURL: String?, selected: Bool, showsCheck: Bool, locked: Bool = false) {
|
||
let placeholder = UIImage(named: "LockDistract/app_unknown")
|
||
if let iconURL, let url = URL(string: iconURL) {
|
||
iconView.kf.setImage(with: url, placeholder: placeholder)
|
||
} else {
|
||
iconView.kf.cancelDownloadTask()
|
||
iconView.image = placeholder
|
||
}
|
||
checkBtn.isSelected = selected
|
||
checkBtn.isHidden = !showsCheck
|
||
lockDimView.isHidden = !locked
|
||
lockIconView.isHidden = !locked
|
||
}
|
||
}
|
||
|
||
final class LockDistractWallpaperCell: UICollectionViewCell {
|
||
private let frameView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = UIColor(hexStr: "#F6F6F6")
|
||
view.cornerRadius = 14
|
||
return view
|
||
}()
|
||
|
||
private let imageView: UIImageView = {
|
||
let iv = UIImageView()
|
||
iv.contentMode = .scaleAspectFill
|
||
iv.cornerRadius = 10
|
||
iv.clipsToBounds = true
|
||
return iv
|
||
}()
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: frame)
|
||
contentView.addSubview(frameView)
|
||
frameView.addSubview(imageView)
|
||
frameView.layoutChain.edges()
|
||
imageView.layoutChain
|
||
.centerY()
|
||
.centerX()
|
||
.width(40)
|
||
.height(40)
|
||
}
|
||
|
||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||
|
||
func configure(imageName: String, isSelected: Bool) {
|
||
imageView.image = UIImage(named: imageName)
|
||
frameView.backgroundColor = UIColor(hexStr: isSelected ? "#EAF8FF" : "#F6F6F6")
|
||
frameView.borderWidth = isSelected ? 1.5 : 0
|
||
frameView.borderColor = UIColor(hexStr: isSelected ? "#00ADFE" : "")
|
||
}
|
||
}
|