iOS开发之自定义日历控件
前言
日常开发中经常会遇到日期选择,为了方便使用,简单封装了一个日历控件,在此抛砖引玉供大家参考。
效果
功能
- 支持单选、区间
- 支持默认选中日期
- 支持限制月份
- 支持过去、当前、未来模式
- 支持
frame、AutoLayout
原理
层次结构使用UIStackView布局,UICollectionView复用,背景使用DecorationView。
核心代码
日历核心代码在于计算每个月的日期,主要代码如下:
func month() -> [CLCalendarMonthModel] {
func day(with date: Date, section: Int) -> [CLCalendarDayModel] {
var newDate = date
let tatalDay = newDate.daysInMonth
let firstDay = max(0, newDate.weekday - 1)
let columns = Int(ceil(CGFloat(tatalDay + firstDay) / CGFloat(weekArray.count)))
var resultArray = [CLCalendarDayModel]()
for column in 0 ..< columns {
for weekDay in 0 ..< weekArray.count {
if column == 0,
weekDay <= firstDay - 1
{
resultArray.append(CLCalendarDayModel())
} else {
let subtitle: String? = {
guard !newDate.isToday else { return "今天" }
guard config.isShowLunarCalendar else { return nil }
guard let index = chinese.dateComponents([.day], from: newDate).day else { return nil }
return chineseDayArray[index - 1]
}()
let type: CLCalendarDayModel.CLCalendarDayType = {
guard !newDate.isToday else { return .today }
guard newDate.compare(todayDate) == .orderedDescending else { return .future }
return .past
}()
let dayModel = CLCalendarDayModel(title: "\(newDate.day)", date: newDate, subtitle: subtitle, type: type)
resultArray.append(dayModel)
newDate = newDate + 1.days
if beginDate?.year == dayModel.date?.year,
beginDate?.month == dayModel.date?.month,
beginDate?.day == dayModel.date?.day
{
startIndexPath = .init(row: 0, section: section)
}
guard (resultArray.count - firstDay) != tatalDay else { break }
}
}
}
return resultArray
}
var resultArray = [CLCalendarMonthModel]()
let month: Int = {
var value = 0
if config.type == .past {
value = config.limitMonth - 1
} else if config.type == .today {
value = config.limitMonth / 2
}
return value
}()
let start = todayDate - month.months
for i in 0 ..< config.limitMonth {
let date = start + i.months
let headerModel = CLCalendarMonthModel(headerText: date.format(with: "yyyy年MM月"),
month: date.format(with: "MM"),
daysArray: day(with: Date(year: date.year, month: date.month, day: 1), section: i))
resultArray.append(headerModel)
}
return resultArray
}
基础配置
struct CLCalendarConfig {
enum CLCalendarType {
case past
case today
case future
}
enum CLSelectType {
case single
case area
}
struct CLTouchType: OptionSet {
static let past = CLTouchType(rawValue: 1)
static let today = CLTouchType(rawValue: 1 << 1)
static let future = CLTouchType(rawValue: 1 << 2)
let rawValue: Int64
init(rawValue: Int64) {
self.rawValue = rawValue
}
}
struct CLColor {
var background = "#ffffff".uiColor
var topToolBackground = "#F4F4F4".uiColor
var topToolText = "#444444".uiColor
var topToolTextWeekend = "#3CCA79".uiColor
var sectionBackgroundText = "f2f2f2".uiColor
var selectStartBackground = "#4bce817f".uiColor
var selectBackground = "#afe9c77f".uiColor
var selectEndBackground = "#4bce817f".uiColor
var todayText = "#32cd32".uiColor
var titleText = "#555555".uiColor
var subtitleText = "#555555".uiColor
var selectTodayText = "#32cd32".uiColor
var selectTitleText = "#ffffff".uiColor
var selectSubtitleText = "#ffffff".uiColor
var failureTitleText = "#a9a9a9".uiColor
var failureSubtitleText = "#a9a9a9".uiColor
var failureBackground = "#dcdcdc32".uiColor
}
var color = CLColor()
var selectBegin: Date?
var selectEnd: Date?
var limitMonth = 12
var type = CLCalendarType.today
var selectType = CLSelectType.area
var touchType: CLTouchType = [.today, .past]
var isShowLunarCalendar = true
var insetsLayoutMarginsFromSafeArea = true
var headerHight = 50.0
}
总结
定制化开发请自行参考CLDemo修改 , 如果喜欢,欢迎star。
参考资料
iOS开发之自定义日历控件的更多相关文章
- iOS开发UI篇—UITableview控件基本使用
iOS开发UI篇—UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) #import <Foundation/Foundation.h> ...
- iOS开发UI篇—UITableview控件使用小结
iOS开发UI篇—UITableview控件使用小结 一.UITableview的使用步骤 UITableview的使用就只有简单的三个步骤: 1.告诉一共有多少组数据 方法:- (NSInteger ...
- javascript实例学习之六—自定义日历控件
基于之前上篇博客轻量级jquery,tool.js和base.js.自定义开发的base_datePicker插件,效果类似于jquery_ui的datePicker插件 //基于Base.js以及t ...
- iOS开发UI篇—UIScrollView控件实现图片缩放功能
iOS开发UI篇—UIScrollView控件实现图片缩放功能 一.缩放 1.简单说明: 有些时候,我们可能要对某些内容进行手势缩放,如下图所示 UIScrollView不仅能滚动显示大量内容,还能对 ...
- iOS开发UI篇—UIScrollView控件介绍
iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...
- iOS开发UI篇—UITableview控件简单介绍
iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...
- iOS开发UI篇—UIScrollView控件实现图片轮播
iOS开发UI篇—UIScrollView控件实现图片轮播 一.实现效果 实现图片的自动轮播 二.实现代码 storyboard中布局 代码: #import "YYV ...
- 【转】 iOS开发UI篇—UIScrollView控件实现图片轮播
原文:http://www.cnblogs.com/wendingding/p/3763527.html iOS开发UI篇—UIScrollView控件实现图片轮播 一.实现效果 实现图片的自动轮播 ...
- ios开发中关闭textview控件的虚拟键盘
在ios开发中,textfield控件在点击的时候出现虚拟键盘,关掉虚拟键盘可以通过虚拟键盘中的done button和点击view中的任意地方来关闭虚拟键盘. 1.第一种方法是textfield控件 ...
随机推荐
- Python 实现列表与二叉树相互转换并打印二叉树封装类-详细注释+完美对齐
# Python 实现列表与二叉树相互转换并打印二叉树封装类-详细注释+完美对齐 from binarytree import build import random # https://www.cn ...
- 喜讯:“行走的文档” 当选 Apache DolphinScheduler Committer啦
点击上方蓝字关注 Apache DolphinScheduler Apache DolphinScheduler(incubating),简称"DS", 中文名 "海豚调 ...
- java学习第一天.day04
顺序结构 代码里没有流程控制,程序是按照书写的格式从上而下一行一行执行的, 一条语句执行完之后继续执行下一条语句,中间没有判断和跳转,直到程序的结束. 选择结构 选择结构也被称为分支结构.代码根据逻辑 ...
- 209. 长度最小的子数组--LeetCode
来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/minimum-size-subarray-sum 著作权归领扣网络所有.商业转载请联系官方授权,非商业 ...
- bind搭建内网DNS服务器架构(主从、子域授权、DNS转发器)
实验目的 模拟企业DNS服务架构服务器及原理 实验环境准备 实验架构图 实验设备 DNS服务器4台 主服务器master(centos8):IP_192.168.100.30, 从服务器slave(r ...
- pod资源的健康检查-readiness探针的httpGet使用
livenessProbe:健康状态检查,周期性检查服务是否存活,检查结果失败,将重启容器 readinessProbe:可用性检查,周期性检查服务是否可用,不可用将从service的endpoint ...
- python进阶__用socket封装TCP
想要理解socket协议,点击链接,出门左转 一.TCP 通信的服务器端编程的基本步骤: 服务器端先创建一个 socket 对象. 服务器端 socket 将自己绑定到指定 IP 地址和端口. 服务器 ...
- 02_Linux基础-文件系统层次结构-提示符-进程-命令格式-隐藏文件-通配符-绝对相对路径-{1..100}-ls-mkdir-其他基础命令
02_Linux基础-ls-mkdir-cd-pwd-man-useradd-su-rm-tree-tab-passwd-w-ssh-touch-date-stat-cp-mv-du-文件系统层次结构 ...
- JUC锁:核心类AQS源码详解
目录 1 疑点todo和解疑 2 AbstractQueuedSynchronizer学习总结 2.1 AQS要点总结 2.2 细节分析 2.2.1 插入节点时先更新prev再更新前驱next 2.2 ...
- 【读书笔记】C#高级编程 第五章 泛型
(一)泛型概述 泛型不仅是C#编程语言的一部分,而且与程序集中的IL代码紧密地集成.泛型不仅是C#语言的一种结构,而且是CLR定义的.有了泛型就可以创建独立于被包含类型的类和方法了. 1.性能 泛型的 ...