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)
|
|||
|
|
// }
|
|||
|
|
}
|