当前位置: 首页 > news >正文

swift 自定义DatePacker

请添加图片描述

import Foundationenum AppDatePickerStyle {case KDatePickerDate    //年月日case KDatePickerTime    //年月日时分case kDatePickerMonth // 年月case KDatePickerSecond  //秒}class AppDatePicker: UIView {private let jk_rootView = UIApplication.shared.keyWindow!private var jk_backgroundView: UIView!private var confirmHandler: (( _ year: Int, _ month: Int,_ day: Int) -> Void)?//选择的回调var cancelHandler: (() -> Void)?//取消的回调/// 选择器类型fileprivate var datePickerStyle: AppDatePickerStyle!/// 时间数据fileprivate var unitFlags:Set<Calendar.Component>!var pickerView = UIPickerView()//数据相关fileprivate var yearRange = 30 + 1000//年的范围fileprivate var dayRange = 0 //fileprivate var startYear = 0// 当前选中日期fileprivate var selectedYear = 0;fileprivate var selectedMonth = 0;fileprivate var selectedDay = 0;fileprivate var selectedHour = 0;fileprivate var selectedMinute = 0;fileprivate var selectedSecond = 0;override init(frame: CGRect) {super.init(frame: frame)}convenience init(title: String = "选择日期", type: AppDatePickerStyle, confirmHandler: @escaping (_ year:Int,_ month:Int,_ day:Int) -> Void) {self.init(frame: .zero)configUI()self.confirmHandler = confirmHandlerjk_titleLabel.text = titleinitDatePickerWithType(type: type)}convenience init(title: String = "选择日期", year: Int, month: Int, day: Int, confirmHandler: @escaping (_ year:Int,_ month:Int,_ day:Int) -> Void) {self.init(frame: .zero)configUI()self.confirmHandler = confirmHandlerjk_titleLabel.text = titleinitDatePickerWithType(type: .kDatePickerMonth, date: year == -1 ? nil:Date.dateFor("\(year)-\(month)-\(day)"))}private func getHeight() -> CGFloat {return CGFloat(56 + 4 * 50 + 56)}// MARK: - UIButtonAction@objc private func confimBtnAction() {if let holder = confirmHandler {holder(selectedYear, selectedMonth, selectedDay)}hide()}// MARK: - configUIfunc configUI() {// 防止多个 AlertView 重复显示if jk_rootView.subviews.filter({ $0.isKind(of: AppDatePicker.self) }).count > 0 { return }jk_backgroundView = UIView()jk_backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0)jk_rootView.addSubview(jk_backgroundView)jk_rootView.addSubview(self)addSubview(jk_backView)jk_backView.addSubview(cornerBackView)cornerBackView.addSubview(jk_titleLabel)cornerBackView.addSubview(pickerView)cornerBackView.addSubview(jk_cancelBtn)cornerBackView.addSubview(conformBtn)cornerBackView.addSubview(verticalLineView)jk_backgroundView.snp.makeConstraints { (make) inmake.edges.equalTo(jk_rootView)}let height = getHeight()snp.makeConstraints { make inmake.left.right.equalToSuperview()make.height.equalTo(height + Size.safeAreaBottomGap)make.bottom.equalTo(height + Size.safeAreaBottomGap)}jk_backView.snp.makeConstraints { make inmake.edges.equalToSuperview()}cornerBackView.snp.makeConstraints { make inmake.left.top.right.equalToSuperview()make.height.equalTo(height)}jk_titleLabel.snp.makeConstraints { make inmake.height.equalTo(40)make.top.equalTo(16)make.left.right.equalToSuperview()}pickerView.snp.makeConstraints { make inmake.top.equalTo(jk_titleLabel.snp.bottom)make.left.right.equalToSuperview()make.height.equalTo(50 * 4)}jk_cancelBtn.snp.makeConstraints { make inmake.height.equalTo(56)make.top.equalTo(pickerView.snp.bottom)make.left.equalToSuperview()make.width.equalToSuperview().multipliedBy(0.5)}conformBtn.snp.makeConstraints { make inmake.right.equalToSuperview()make.centerY.height.width.equalTo(jk_cancelBtn)}verticalLineView.snp.makeConstraints { make inmake.height.equalTo(20)make.width.equalTo(1)make.centerY.equalTo(jk_cancelBtn)make.centerX.equalToSuperview()}self.jk_rootView.layoutIfNeeded()let tapGR = UITapGestureRecognizer.init(target: self, action: #selector(hideAction))jk_backgroundView.addGestureRecognizer(tapGR)jk_cancelBtn.addTarget(self, action: #selector(hideAction), for: .touchUpInside)conformBtn.addTarget(self, action: #selector(confimBtnAction), for: .touchUpInside)pickerView.delegate = selfpickerView.dataSource = self}private lazy var jk_backView: UIView = {let jk_backView = UIView()jk_backView.backgroundColor = .whitereturn jk_backView}()private lazy var cornerBackView: UIView = {let cornerBackView = UIView()cornerBackView.backgroundColor = .whitereturn cornerBackView}()private lazy var jk_titleLabel: UILabel = {let jk_titleLabel = UILabel()jk_titleLabel.textAlignment = .centerjk_titleLabel.font = kSetPingFangMedium(18)return jk_titleLabel}()private lazy var jk_cancelBtn: UIButton = {let jk_cancelBtn = UIButton()jk_cancelBtn.setTitle("取消", for: .normal)jk_cancelBtn.setTitleColor( .black, for: .normal)return jk_cancelBtn}()private lazy var verticalLineView: UIView = {let verticalLineView = UIView()verticalLineView.backgroundColor = .jky_viewBackgroundColorreturn verticalLineView}()private lazy var conformBtn: UIButton = {let conformBtn = UIButton()conformBtn.setTitle("确定", for: .normal)conformBtn.setTitleColor( .black, for: .normal)return conformBtn}()required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)fatalError("init(coder:) has not been implemented")}
}//MARK:初始化数据
extension AppDatePicker {fileprivate func initDatePickerWithType(type: AppDatePickerStyle, date: Date? = nil)  {datePickerStyle = typelet  calendar0 = Calendar.init(identifier: .gregorian)//公历var comps = DateComponents()//一个封装了具体年月日、时秒分、周、季度等的类unitFlags = [.year , .month , .day]switch  datePickerStyle {case .KDatePickerDate:breakcase .KDatePickerTime:unitFlags = [.year , .month , .day , .hour , .minute ]case .kDatePickerMonth:unitFlags = [.year , .month]case .KDatePickerSecond:unitFlags = [.year , .month , .day , .hour , .minute ,.second]default:break}//        comps = calendar0.dateComponents(unitFlags, from: date != nil ? date! : Date())comps = calendar0.dateComponents(unitFlags, from: date != nil ? date!:Date())startYear = comps.year! - 100dayRange = self.isAllDay(year: startYear, month: 1)yearRange = 30 + 1000;selectedYear = comps.year!;selectedMonth = comps.month!;self.pickerView.selectRow(selectedYear - startYear, inComponent: 0, animated: true)self.pickerView.selectRow(selectedMonth - 1, inComponent: 1, animated: true)if datePickerStyle != .kDatePickerMonth {selectedDay = comps.day!;self.pickerView.selectRow(selectedDay - 1, inComponent: 2, animated: true)}switch  datePickerStyle {case .KDatePickerDate:breakcase .KDatePickerTime:selectedHour = comps.hour!;selectedMinute = comps.minute!;self.pickerView.selectRow(selectedHour , inComponent: 3, animated: true)self.pickerView.selectRow(selectedMinute , inComponent: 4, animated: true)case .KDatePickerSecond:selectedHour = comps.hour!;selectedMinute = comps.minute!;selectedSecond = comps.second!;self.pickerView.selectRow(selectedHour , inComponent: 3, animated: true)self.pickerView.selectRow(selectedMinute , inComponent: 4, animated: true)self.pickerView.selectRow(selectedSecond, inComponent: 5, animated: true)default:break}self.pickerView.reloadAllComponents()}//MARK:计算每个月有多少天fileprivate func isAllDay(year:Int, month:Int) -> Int {var   day:Int = 0switch(month){case 1,3,5,7,8,10,12:day = 31case 4,6,9,11:day = 30case 2:if(((year%4==0)&&(year%100==0))||(year%400==0)){day=29}else{day=28;}default:break;}return day;}}extension AppDatePicker : UIPickerViewDelegate,UIPickerViewDataSource {//返回UIPickerView当前的列数func numberOfComponents(in pickerView: UIPickerView) -> Int {return unitFlags == nil ? 0 : unitFlags.count}//确定每一列返回的东西func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {switch component {case 0:return yearRangecase 1:return 12case 2:return dayRangecase 3:return 24case 4:return 60case 5:return 60default:return 0}}func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {return 45}//返回一个视图,用来设置pickerView的每行显示的内容。func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {let label  = UILabel(frame: CGRect(x: screenWidth * CGFloat(component) / 6 , y: 0, width: screenWidth/6, height: 50))label.font = UIFont.boldSystemFont(ofSize: CGFloat(16))label.tag = component*100+rowlabel.textAlignment = .centerswitch component {case 0:label.frame=CGRect(x:5, y:0,width:screenWidth/4.0, height:50);label.text="\(self.startYear + row)年";case 1:label.frame=CGRect(x:screenWidth/4.0, y:0,width:screenWidth/8.0, height:50);label.text="\(row + 1)月";case 2:label.frame=CGRect(x:screenWidth*3/8, y:0,width:screenWidth/8.0, height:50);label.text="\(row + 1)日";case 3:label.textAlignment = .rightlabel.text="\(row )时";case 4:label.textAlignment = .rightlabel.text="\(row )分";case 5:label.textAlignment = .rightlabel.frame=CGRect(x:screenWidth/6, y:0,width:screenWidth/6.0 - 5, height:50);label.text="\(row )秒";default:label.text="\(row )秒";}return label}//当点击UIPickerView的某一列中某一行的时候,就会调用这个方法func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {switch component {case 0:self.selectedYear = self.startYear + rowself.dayRange = self.isAllDay(year: self.startYear, month: self.selectedMonth)if datePickerStyle != .kDatePickerMonth {self.pickerView.reloadComponent(2)}case 1:self.selectedMonth =  row + 1self.dayRange = self.isAllDay(year: self.startYear, month: self.selectedMonth)if datePickerStyle != .kDatePickerMonth {self.pickerView.reloadComponent(2)}case 2:selectedDay = row + 1case 3:selectedHour = rowcase 4:selectedMinute = rowcase 5:selectedSecond = rowdefault:selectedSecond = row}}}extension AppDatePicker: UIGestureRecognizerDelegate {func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {if let view = touch.view, view.isDescendant(of: pickerView) {return false}return true}func show() {self.jk_backView.layerCornerRadius(16, [.topLeft,.topRight])UIView.animate(withDuration: 0.2, animations: {self.jk_backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5)self.snp.updateConstraints { make inmake.bottom.equalTo(0)}self.jk_rootView.layoutIfNeeded()})}@objc private func hideAction() {if let holder = cancelHandler {holder()}hide()}private func hide(completion: (() -> Void)? = nil) {UIView.animate(withDuration: 0.2, animations: {self.jk_backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0)self.snp.updateConstraints { make inmake.bottom.equalTo(self.getHeight() + Size.safeAreaBottomGap)}self.jk_rootView.layoutIfNeeded()}) { finished inguard finished else { return }self.removeFromSuperview()self.jk_backgroundView.removeFromSuperview()}}}

相关文章:

swift 自定义DatePacker

import Foundationenum AppDatePickerStyle {case KDatePickerDate //年月日case KDatePickerTime //年月日时分case kDatePickerMonth // 年月case KDatePickerSecond //秒}class AppDatePicker: UIView {private let jk_rootView UIApplication.shared.keyWindow!pri…...

MySQL事务,锁,MVCC总结

mysql中最重要的就是事务&#xff0c;其四大特性让我们维持了数据的平衡&#xff0c;一致。那么事务究竟是什么&#xff0c;与什么相关&#xff0c;他的使用步骤&#xff0c;以及使用过程中我们会遇到什么问题呢&#xff1f;下面我们一起学习交流! 1.MySQL的存储引擎&#xff…...

24/8/7 算法笔记 支持向量机回归问题天猫双十一

import numpy as np from sklearn.svm import SVR import matplotlib.pyplot as plt X np.linspace(0,2*np.pi,50).reshape(-1,1) y np.sin(X) plt.scatter(X,y) 建模 线性核函数 svr SVR(kernel linear) svr.fit(X,y.ravel())#变成一维y_ svr.predict(X) plt.scatter(…...

win7系统利用定时启动+脚本实现MySQL文件自动备份

前言 最近接到项目&#xff0c;数据量不大但对运行数据的安全性要求极高&#xff0c;为避免因不可抗拒因素导致的数据丢失&#xff0c;选择机械硬盘作为数据存储盘&#xff0c;并使用脚本方式对文件进行备份 一、脚本 下面为自动备份文件的 脚本&#xff0c;可根据自身情况进…...

基于Java多线程处理数据

基于Java多线程处理数据 背景代码实现 背景 在日常工作中&#xff0c;有一个同步企微客户-学员关系接口的定时任务在执行中随着数据量的不断增长&#xff0c;定时任务的执行结束时间也出现了当天执行不完的情况&#xff0c;影响到了正常业务的运行。基于这种情况&#xff0c;在…...

日常知识点之遇到问题结构体按位构造协议时和期望不一致,研究记录一下

遇到一个问题&#xff0c;在做业务的时候&#xff0c;涉及到协议相关&#xff0c;按位进行设计&#xff0c;用结构体来模拟协议时&#xff0c;发现内存存储和实际目的不一致&#xff0c;知道是大小端以及计算机底层存储逻辑相关&#xff0c;所以研究了一下。 1&#xff1a;简单…...

spring mvc 文件下载

在web中下载的方式大多基于servlet&#xff0c;在web.xml中配置下载路径&#xff0c;这里再介绍json(转成base64字符串)和blob的使用方式 servlet WEB-INF/web.xml <!--url映射--> <servlet-mapping><servlet-name>DowloadServlet</servlet-name>&l…...

Qt WebEngine基于WebEngineScript注入js脚本

在之前的文章中&#xff0c;我们介绍了Qt WebEngine注入js的用法&#xff0c;及runJavaScript()的用法&#xff0c;该方法主要是用在页面加载完成后&#xff0c;为了和网页做一些交互时使用。有时候需要监听网页加载完成的一些状态或信息&#xff0c;则需要网页加载前注入js来实…...

案例分享-国外UI设计界面赏析

国外UI设计倾向于简洁的布局和清晰的排版&#xff0c;减少视觉干扰&#xff0c;提升用户体验。通过合理的色彩搭配和图标设计&#xff0c;营造舒适愉悦的使用氛围。 设计师不拘泥于传统框架&#xff0c;勇于尝试新元素和理念&#xff0c;使界面独特有趣。同时&#xff0c;强调以…...

用PyTorch 从零开始构建 BitNet 1.58bit

我们手动实现BitNet的编写&#xff0c;并进行的一系列小实验证实&#xff0c;看看1.58bit 模型是否与全精度的大型语言模型相媲美&#xff01; 什么是量化以及为什么需要它&#xff1f; 量化是用更少的比特数表示浮点数的过程。当两个数字使用不同的比特数进行量化时&#xf…...

信创安全 | 新一代内网安全方案—零信任沙盒

在当今数字化时代&#xff0c;访问安全和数据安全成为企业面临的重要挑战。传统的边界防御已经无法满足日益复杂的内网办公环境&#xff0c;层出不穷的攻击手段已经让市场单一的防御手段黔驴技穷。当企业面临越来越复杂的网络威胁和数据泄密风险时&#xff0c;更需要一种综合的…...

Redis的回收策略(淘汰策略)

volatile-lru &#xff1a;从已设置过期时间的数据集&#xff08; server.db[i].expires &#xff09;中挑选最近最少使用的数据淘汰 volatile-ttl &#xff1a; 从已设置过期时间的数据集&#xff08; server.db[i].expires &#xff09; 中挑选将要过期的数据淘汰 volatile…...

Electron-builder 打包

项目比较简单&#xff0c;仅使用了 Electron 原生js 安装 electron-builder npm install electron-builder --dev配置 package.json 中的打包命令 {"script":{// ..."dev": "electron .","pack": "electron-builder"} }添…...

笔试练习day3

目录 BC149 简写单词题目解析代码 dd爱框框题目解析解析代码方法一暴力解法方法二同向双指针(滑动窗口) 除2!题目解析解法模拟贪心堆 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &#x1f978;&#x1…...

企业想要将大模型技术应用到企业管理中需具备什么条件?

#企业 #企业管理 #大模型 企业想要将大模型技术应用到企业管理中&#xff0c;需要考虑以下几个关键条件&#xff1a; 1.明确的需求定位&#xff1a;企业应首先诊断自身的业务场景、数据、算法、基础设施预算以及战略等能力&#xff0c;明确大模型能够为企业带来的具体赋…...

go 事件机制(观察者设计模式)

背景&#xff1a; 公司目前有个业务&#xff0c;收到数据后&#xff0c;要分发给所有的客户端或者是业务模块&#xff0c;类似消息通知这样的需求&#xff0c;自然而然就想到了事件&#xff0c;观察者比较简单就自己实现以下&#xff0c;确保最小功能使用支持即可&#xff0c;其…...

RISC-V竞赛|第二届 RISC-V 软件移植及优化锦标赛报名正式开始!

目录 赛事背景 赛道方向 适配夺旗赛 优化竞速赛 比赛赛题&#xff08;总奖金池8万元&#xff01;&#xff09; &#x1f525;竞速赛 - OceanBase 移植与优化 比赛赛程&#xff08;暂定&#xff09; 赛事说明 「赛事背景」 为了推动 RISC-V 软件生态更快地发展&#xff0…...

【VTK】ubuntu手动编译VTK9.3 Generating qmltypes file 失败

环境 硬件&#xff1a;Jetson Xavier NX 套件 系统&#xff1a;Ubuntu 20.04 软件 &#xff1a;QT5.15.6 解决 0、问题 最近在Jetson Xavier NX 套件上编译VTK库&#xff0c;因为想要配合QQuick使用&#xff0c;所以cmake配置时勾选了VTK_MODULE_ENABLE_VTK_GUISupportQtQu…...

学习java的日子 Day64 学生管理系统 web2.0 web版本

MVC设计模式 概念 - 代码的分层 MVC&#xff1a;项目分层的思想 字母表示层理解MModle模型层业务的具体实现VView视图层展示数据CController控制器层控制业务流程&#xff08;跳转&#xff09; 1.细化理解层数 Controller&#xff1a;控制器层&#xff0c;用于存放Servlet&…...

【第14章】Spring Cloud之Gateway路由断言(IP黑名单)

文章目录 前言一、内置路由断言1. 案例&#xff08;Weight&#xff09;2. 更多断言 二、自定义路由断言1. 黑名单断言2. 全局异常处理3. 应用配置4. 单元测试 总结 前言 Spring Cloud Gateway可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...

[特殊字符] Spring Boot底层原理深度解析与高级面试题精析

一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配&#xff0c;通过简化传统Spring应用的初始化和配置流程&#xff0c;显著提升开发效率。其底层原理可拆解为以下核心机制&#xff1a; 自动装配&#xff08;Auto-Configuration&#xff09; 核…...

C/Python/Go示例 | Socket Programing与RPC

Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流&#xff0c;会涉及到许多有意思的话题&#xff0c;诸如怎么确保对方能收到信息&#xff0c;怎么应对数据丢失、被污染或者顺序混乱&#xff0c;怎么提高…...

python数据结构和算法(1)

数据结构和算法简介 数据结构&#xff1a;存储和组织数据的方式&#xff0c;决定了数据的存储方式和访问方式。 算法&#xff1a;解决问题的思维、步骤和方法。 程序 数据结构 算法 算法 算法的独立性 算法是独立存在的一种解决问题的方法和思想&#xff0c;对于算法而言&a…...