188 lines
5.8 KiB
Swift
188 lines
5.8 KiB
Swift
//
|
||
// BirthdayPickerView.swift
|
||
// Crush
|
||
//
|
||
// Created by Leon on 2025/7/19.
|
||
//
|
||
|
||
import SnapKit
|
||
import UIKit
|
||
|
||
class BirthdayPickerView: EGPopBaseView {
|
||
// MARK: - Properties
|
||
|
||
private var titleLabel: UILabel
|
||
let pickerView: CLDatePicker
|
||
let confirmButton: TickButton
|
||
private var closeButton: EPIconGhostButton
|
||
private var defaultDate: Date?
|
||
|
||
var selectBirthday: ((Date, Int) -> Void)?
|
||
var tapCancelAction: (() -> Void)?
|
||
var tapConfirmAction: ((Date, Int) -> Void)?
|
||
|
||
var optionMinimumDate: Date? {
|
||
didSet {
|
||
if let minimumDate = optionMinimumDate {
|
||
pickerView.minimumDate = minimumDate
|
||
}
|
||
}
|
||
}
|
||
|
||
init() {
|
||
titleLabel = UILabel()
|
||
pickerView = CLDatePicker()
|
||
confirmButton = TickButton()
|
||
closeButton = EPIconGhostButton(radius: .none, iconSize: .small, iconCode: .delete)
|
||
|
||
super.init(direction: .bottom)
|
||
|
||
contentView.backgroundColor = .c.csbn
|
||
|
||
// 默认选择的最小年月和默认年月
|
||
optionMinimumDate = Date(year: 1960, month: 1, day: 1)
|
||
pickerView.setDate(Date(year: 2000, month: 1, day: 1), animated: false)
|
||
|
||
initialData()
|
||
initialViews()
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
// MARK: - Setup
|
||
|
||
private func initialData() {
|
||
contentLength = 268 + UIWindow.safeAreaBottom
|
||
}
|
||
|
||
private func initialViews() {
|
||
// Title view
|
||
let titleView = UIView()
|
||
titleView.backgroundColor = .clear
|
||
contentView.addSubview(titleView)
|
||
titleView.snp.makeConstraints { make in
|
||
make.left.right.equalTo(contentView)
|
||
make.top.equalTo(contentView).offset(12)
|
||
make.height.equalTo(48)
|
||
}
|
||
|
||
// Close button
|
||
closeButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
|
||
titleView.addSubview(closeButton)
|
||
closeButton.snp.makeConstraints { make in
|
||
make.centerY.equalTo(titleView)
|
||
make.left.equalTo(titleView).offset(12)
|
||
make.size.equalTo(CGSize(width: 48, height: 48))
|
||
}
|
||
|
||
// Confirm button
|
||
confirmButton.isEnabled = true
|
||
confirmButton.addTarget(self, action: #selector(confirmAction), for: .touchUpInside)
|
||
titleView.addSubview(confirmButton)
|
||
confirmButton.snp.makeConstraints { make in
|
||
make.centerY.equalTo(titleView)
|
||
make.right.equalTo(titleView).offset(-24)
|
||
}
|
||
|
||
// Title label
|
||
titleLabel.font = CLSystemToken.font(token: .tts) // EPSystemToken.typography(.txtTitleS).font
|
||
titleLabel.textColor = .c.ctpn // EPSystemToken.color(.txtPrimaryNormal)
|
||
titleLabel.textAlignment = .center
|
||
titleView.addSubview(titleLabel)
|
||
titleLabel.snp.makeConstraints { make in
|
||
make.center.equalTo(titleView)
|
||
}
|
||
titleLabel.text = NSLocalizedString("select", comment: "")
|
||
|
||
// Date picker
|
||
if #available(iOS 13.4, *) {
|
||
pickerView.preferredDatePickerStyle = .wheels
|
||
}
|
||
contentView.addSubview(pickerView)
|
||
pickerView.snp.makeConstraints { make in
|
||
make.left.right.equalTo(contentView)
|
||
make.top.equalTo(titleView.snp.bottom)
|
||
make.bottom.equalTo(contentView).offset(-UIWindow.safeAreaBottom)
|
||
}
|
||
pickerView.datePickerMode = .date
|
||
pickerView.maximumDate = Date()
|
||
pickerView.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged)
|
||
|
||
// 设置 textColor
|
||
pickerView.setValue(UIColor.c.ctpn, forKey: "textColor")
|
||
|
||
// 调用 setHighlightsToday:(私有 API,注意 App Store 风险)
|
||
let selector = Selector(("setHighlightsToday:"))
|
||
if pickerView.responds(to: selector) {
|
||
pickerView.perform(selector, with: false)
|
||
}
|
||
|
||
// // Theming for picker view
|
||
// pickerView.setValue(UIColor.cl.ctpn, forKey: "textColor")
|
||
// if let selector = NSSelectorFromString("setHighlightsToday:") {
|
||
// var no = false
|
||
// let invocation = NSInvocation.invocation(withMethodSignature: UIDatePicker.instanceMethodSignature(for: selector))
|
||
// invocation.selector = selector
|
||
// invocation.setArgument(&no, atIndex: 2)
|
||
// invocation.invoke(withTarget: item)
|
||
// }
|
||
|
||
// Set default minimum date
|
||
pickerView.minimumDate = Date(year: 1950, month: 1, day: 1)
|
||
|
||
titleLabel.textColor = .c.ctpn // EPSystemToken.color(.txtPrimaryNormal)
|
||
}
|
||
|
||
// MARK: - Actions
|
||
|
||
@objc private func cancelAction() {
|
||
tapCancelAction?()
|
||
if superview != nil {
|
||
dismiss()
|
||
}
|
||
}
|
||
|
||
@objc private func confirmAction() {
|
||
defaultDate = pickerView.date
|
||
let timestamp = Int(pickerView.date.timeIntervalSince1970)
|
||
tapConfirmAction?(pickerView.date, timestamp)
|
||
if superview != nil {
|
||
dismiss()
|
||
}
|
||
}
|
||
|
||
@objc private func dateChanged(_ datePicker: UIDatePicker) {
|
||
let date = datePicker.date
|
||
let timestamp = Int(date.timeIntervalSince1970)
|
||
selectBirthday?(date, timestamp)
|
||
}
|
||
|
||
// MARK: - Public Methods
|
||
|
||
func setupDefaultSelectDate(_ date: Date?) {
|
||
guard let date = date else { return }
|
||
defaultDate = date
|
||
pickerView.setDate(date, animated: false)
|
||
}
|
||
}
|
||
|
||
// MARK: - Extensions
|
||
|
||
extension Date {
|
||
init(year: Int, month: Int, day: Int) {
|
||
let calendar = Calendar.current
|
||
var components = DateComponents()
|
||
components.year = year
|
||
components.month = month
|
||
components.day = day
|
||
self = calendar.date(from: components) ?? Date()
|
||
}
|
||
|
||
// var timestamp: Int64 {
|
||
// Int64(timeIntervalSince1970)
|
||
// }
|
||
}
|