jsdw_ios/QuickLocation/Section/Home/MemberPhoneReportView.swift

317 lines
11 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MemberPhoneReportView.swift
// QuickLocation
//
import UIKit
struct MemberPhoneReportPreview {
let screenTimeSeconds: Int?
let usageCount: Int
let unlockCount: Int
static func currentUser(from manager: UnlockCountManager = .shared) -> MemberPhoneReportPreview {
let seconds = manager.todayScreenTimeSeconds
return MemberPhoneReportPreview(
screenTimeSeconds: seconds > 0 ? seconds : nil,
usageCount: manager.todayAppUsageCount,
unlockCount: manager.todayCount
)
}
}
/// 使 + 使 +
final class MemberPhoneReportView: UIView {
private enum Layout {
static let designCardWidth: CGFloat = 345
static let leftPanelWidthRatio: CGFloat = 164 / designCardWidth
static let leftPanelAspect: CGFloat = 147 / 164
static let panelGap: CGFloat = 13
static let cardInset: CGFloat = 12
static let usageCardAspect: CGFloat = 69 / 146
static let usageUnlockGap: CGFloat = 9
}
private let titleColor = UIColor(hexStr: "#293445")
private let usageTint = UIColor(hexStr: "#E8FBE8")
private let unlockTint = UIColor(hexStr: "#E8F4FF")
private let sectionIcon = UIImageView()
private let sectionTitleLab = UILabel()
private let cardView = UIView()
private let leftPanel = UIView()
private let rightPanel = UIView()
private let screenTimeIcon = UIImageView()
private let screenTimeTitleLab = UILabel()
private let screenTimeBadge = ScreenTimeBadgeView()
private let usageCard = UIView()
private let usageIcon = UIImageView()
private let usageTitleLab = UILabel()
private let usageValueLab = UILabel()
private let unlockCard = UIView()
private let unlockIcon = UIImageView()
private let unlockTitleLab = UILabel()
private let unlockValueLab = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
configure(with: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure(with preview: MemberPhoneReportPreview?) {
if let preview {
screenTimeBadge.configure(seconds: preview.screenTimeSeconds)
usageValueLab.text = "\(preview.usageCount)"
unlockValueLab.text = "\(preview.unlockCount)"
} else {
screenTimeBadge.configure(seconds: nil)
usageValueLab.text = "**"
unlockValueLab.text = "**"
}
}
private func setupUI() {
backgroundColor = .clear
sectionIcon.image = UIImage(named: "Home/member_phone_report")
sectionIcon.contentMode = .scaleAspectFit
addSubview(sectionIcon)
sectionIcon.layoutChain
.top()
.left(15)
.width(18)
.heightToWidth(1)
sectionTitleLab.text = "手机报告"
sectionTitleLab.font = .systemFont(ofSize: 16, weight: .bold)
sectionTitleLab.textColor = titleColor
addSubview(sectionTitleLab)
sectionTitleLab.layoutChain
.leftToRightOfView(sectionIcon, offset: 6)
.centerY(sectionIcon)
cardView.backgroundColor = .white
cardView.cornerRadius = 16
addSubview(cardView)
cardView.layoutChain
.topToBottomOfView(sectionIcon, offset: 12)
.edgesHorzontal(15)
.bottom()
cardView.addSubview(leftPanel)
cardView.addSubview(rightPanel)
leftPanel.backgroundColor = UIColor(hexStr: "#FFFCEA")
leftPanel.cornerRadius = 14
rightPanel.backgroundColor = .clear
leftPanel.layoutChain
.top(Layout.cardInset)
.left(Layout.cardInset)
.widthToView(cardView, multiplier: Layout.leftPanelWidthRatio)
.heightToWidth(Layout.leftPanelAspect)
rightPanel.layoutChain
.top(Layout.cardInset)
.right(Layout.cardInset)
.leftToRightOfView(leftPanel, offset: Layout.panelGap)
.heightToView(leftPanel)
.bottom(Layout.cardInset)
screenTimeIcon.image = UIImage(named: "Home/member_report_clock")
screenTimeIcon.contentMode = .scaleAspectFit
leftPanel.addSubview(screenTimeIcon)
screenTimeIcon.layoutChain
.top(7)
.left(7)
.width(20)
.height(20)
screenTimeTitleLab.text = "屏幕使用时长"
screenTimeTitleLab.font = .systemFont(ofSize: 12, weight: .bold)
screenTimeTitleLab.textColor = UIColor(hexStr: "#293445")
leftPanel.addSubview(screenTimeTitleLab)
screenTimeTitleLab.layoutChain
.leftToRightOfView(screenTimeIcon, offset: 6)
.centerY(screenTimeIcon)
leftPanel.addSubview(screenTimeBadge)
screenTimeBadge.layoutChain
.topToBottomOfView(screenTimeTitleLab, offset: 13)
.centerX(leftPanel, offset: 7)
let screenTimeBadgeArrow = UIImageView(image: UIImage(named: "Home/member_screenTime_arrow"))
leftPanel.addSubview(screenTimeBadgeArrow)
screenTimeBadgeArrow.layoutChain
.topToBottomOfView(screenTimeBadge)
.centerX(screenTimeBadge)
let barchartIcon = UIImageView(image: UIImage(named: "Home/member_screenTime"))
leftPanel.addSubview(barchartIcon)
barchartIcon.layoutChain
.centerX()
.topToBottomOfView(screenTimeBadge, offset: 12)
usageCard.backgroundColor = UIColor(hexStr: "#F8FFEE")
usageCard.cornerRadius = 14
rightPanel.addSubview(usageCard)
usageCard.layoutChain
.top()
.edgesHorzontal()
.heightToWidth(Layout.usageCardAspect)
usageIcon.image = UIImage(named: "Home/member_usage_count")
usageIcon.contentMode = .scaleAspectFit
usageCard.addSubview(usageIcon)
usageIcon.layoutChain
.top(8)
.left(10)
.width(20)
.height(20)
usageTitleLab.text = "使用次数"
usageTitleLab.font = .systemFont(ofSize: 12, weight: .bold)
usageTitleLab.textColor = UIColor(hexStr: "#293445")
usageCard.addSubview(usageTitleLab)
usageTitleLab.layoutChain
.leftToRightOfView(usageIcon, offset: 6)
.centerY(usageIcon)
.right(relation: .lessThanOrEqual)
usageValueLab.font = .systemFont(ofSize: 24, weight: .bold)
usageValueLab.textColor = UIColor(hexStr: "#83DE00")
usageCard.addSubview(usageValueLab)
usageValueLab.layoutChain
.topToBottomOfView(usageTitleLab, offset: 4)
.centerX()
let usageValueUnitLab = UILabel()
usageValueUnitLab.text = ""
usageValueUnitLab.textColor = UIColor(hexStr: "#293445")
usageValueUnitLab.font = .systemFont(ofSize: 12, weight: .bold)
usageCard.addSubview(usageValueUnitLab)
usageValueUnitLab.layoutChain
.leftToRightOfView(usageValueLab, offset: 3)
.bottomToView(usageValueLab, offset: -4)
unlockCard.backgroundColor = UIColor(hexStr: "#F2FEFF")
unlockCard.cornerRadius = 14
rightPanel.addSubview(unlockCard)
unlockCard.layoutChain
.topToBottomOfView(usageCard, offset: Layout.usageUnlockGap)
.edgesHorzontal()
.heightToWidth(Layout.usageCardAspect)
.bottom()
unlockIcon.image = UIImage(named: "Home/member_daily_unlock")
unlockIcon.contentMode = .scaleAspectFit
unlockCard.addSubview(unlockIcon)
unlockIcon.layoutChain
.top(8)
.left(10)
.width(20)
.height(20)
unlockTitleLab.text = "今日解锁"
unlockTitleLab.font = .systemFont(ofSize: 12, weight: .bold)
unlockTitleLab.textColor = UIColor(hexStr: "#293445")
unlockCard.addSubview(unlockTitleLab)
unlockTitleLab.layoutChain
.leftToRightOfView(unlockIcon, offset: 6)
.centerY(unlockIcon)
.right(relation: .lessThanOrEqual)
unlockValueLab.font = .systemFont(ofSize: 24, weight: .bold)
unlockValueLab.textColor = UIColor(hexStr: "#08B6C4")
unlockCard.addSubview(unlockValueLab)
unlockValueLab.layoutChain
.topToBottomOfView(unlockTitleLab, offset: 4)
.centerX()
let unlockValueUnitLab = UILabel()
unlockValueUnitLab.text = ""
unlockValueUnitLab.textColor = UIColor(hexStr: "#293445")
unlockValueUnitLab.font = .systemFont(ofSize: 12, weight: .bold)
unlockCard.addSubview(unlockValueUnitLab)
unlockValueUnitLab.layoutChain
.leftToRightOfView(unlockValueLab, offset: 3)
.bottomToView(unlockValueLab, offset: -4)
}
}
// MARK: - Badge
private final class ScreenTimeBadgeView: UIView {
private let contentStack = UIStackView()
private let numberColor = UIColor(hexStr: "#FF6B4A")
private let unitColor = UIColor(hexStr: "#293445")
private let numberFont = UIFont.systemFont(ofSize: 24, weight: .heavy)
private let unitFont = UIFont.systemFont(ofSize: 14, weight: .heavy)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
cornerRadius = 11
contentStack.axis = .horizontal
contentStack.alignment = .lastBaseline
contentStack.spacing = 2
addSubview(contentStack)
contentStack.layoutChain
.edges(UIEdgeInsets(top: 6, left: 10, bottom: 6, right: 10))
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure(seconds: Int?) {
contentStack.arrangedSubviews.forEach { view in
contentStack.removeArrangedSubview(view)
view.removeFromSuperview()
}
guard let seconds, seconds > 0 else {
contentStack.addArrangedSubview(makeLabel(text: "**", font: numberFont, color: numberColor))
return
}
let hours = seconds / 3600
let minutes = (seconds % 3600) / 60
if hours > 0 {
appendPart(number: "\(hours)", unit: "h")
if minutes > 0 {
contentStack.addArrangedSubview(makeSpacer(width: 4))
appendPart(number: "\(minutes)", unit: "m")
}
} else {
appendPart(number: "\(minutes)", unit: "m")
}
}
private func appendPart(number: String, unit: String) {
contentStack.addArrangedSubview(makeLabel(text: number, font: numberFont, color: numberColor))
contentStack.addArrangedSubview(makeLabel(text: unit, font: unitFont, color: unitColor))
}
private func makeLabel(text: String, font: UIFont, color: UIColor) -> UILabel {
let label = UILabel()
label.text = text
label.font = font
label.textColor = color
return label
}
private func makeSpacer(width: CGFloat) -> UIView {
let spacer = UIView()
spacer.translatesAutoresizingMaskIntoConstraints = false
spacer.widthAnchor.constraint(equalToConstant: width).isActive = true
return spacer
}
}