前言

日常开发中经常会遇到日期选择,为了方便使用,简单封装了一个日历控件,在此抛砖引玉供大家参考。

效果

功能

  • 支持单选、区间
  • 支持默认选中日期
  • 支持限制月份
  • 支持过去、当前、未来模式
  • 支持frameAutoLayout

原理

层次结构使用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。

参考资料

  1. DateToolsSwift

  2. UICollectionView: 装饰视图 Decoration View

  3. 使用UIStackView来简化iOS的界面布局

最新文章

  1. Visual Studio跨平台开发Xamarin
  2. 给Mac OS X的“逻辑宗卷组”改名
  3. mysql utf8编码
  4. 【UOJ #14】【UER #1】DZY Loves Graph
  5. jinfo命令的使用
  6. JStorm之Nimbus简介
  7. 采用CSS3设计的登录界面,动态效果(动画)
  8. MYSQL中约束及修改数据表
  9. 黄聪:在WordPress后台文章编辑器的上方或下方添加提示内容
  10. 高效线程池(threadpool)的实现
  11. 【莫比乌斯反演】关于Mobius反演与lcm的一些关系与问题简化(BZOJ 2154 crash的数字表格&amp;&amp;BZOJ 2693 jzptab)
  12. 【原】lua的table深拷贝
  13. Ecsotre 参考
  14. 深入浅出SOA
  15. C#创建IIS站点及相应的应用程序池,支持IIS6.0+Windows Server 2003. 使用Builder设计模式
  16. NOT NULL constraint faile(慢就是快,少即是多)
  17. Mac os x下几款mysql客户端
  18. 关于数据库DML、DDL、DCL区别
  19. 【WPF】 Behavior
  20. Mac网络命令 老命令重新学

热门文章

  1. 人非圣贤孰能无过,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang错误处理机制EP11
  2. 使用VitePress搭建及部署vue组件库文档
  3. 理解 Flutter 的基础概念:Widget
  4. 如何在Apple Silicon Mac上主动安装Rosetta2
  5. JavaScript之数组常用API
  6. C语言:多功能计算器程序说明书
  7. 第十三章 k8s的GUI资源管理插件--dashboard
  8. KingbaseES 数据脱敏功能介绍
  9. centos7部署k8s(1master1node)
  10. 2022 CLion 中的Cygwin 配置(最全,最良心版)