前言

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

效果

功能

  • 支持单选、区间
  • 支持默认选中日期
  • 支持限制月份
  • 支持过去、当前、未来模式
  • 支持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的界面布局

iOS开发之自定义日历控件的更多相关文章

  1. iOS开发UI篇—UITableview控件基本使用

    iOS开发UI篇—UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) #import <Foundation/Foundation.h> ...

  2. iOS开发UI篇—UITableview控件使用小结

    iOS开发UI篇—UITableview控件使用小结 一.UITableview的使用步骤 UITableview的使用就只有简单的三个步骤: 1.告诉一共有多少组数据 方法:- (NSInteger ...

  3. javascript实例学习之六—自定义日历控件

    基于之前上篇博客轻量级jquery,tool.js和base.js.自定义开发的base_datePicker插件,效果类似于jquery_ui的datePicker插件 //基于Base.js以及t ...

  4. iOS开发UI篇—UIScrollView控件实现图片缩放功能

    iOS开发UI篇—UIScrollView控件实现图片缩放功能 一.缩放 1.简单说明: 有些时候,我们可能要对某些内容进行手势缩放,如下图所示 UIScrollView不仅能滚动显示大量内容,还能对 ...

  5. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

  6. iOS开发UI篇—UITableview控件简单介绍

    iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...

  7. iOS开发UI篇—UIScrollView控件实现图片轮播

    iOS开发UI篇—UIScrollView控件实现图片轮播 一.实现效果 实现图片的自动轮播            二.实现代码 storyboard中布局 代码: #import "YYV ...

  8. 【转】 iOS开发UI篇—UIScrollView控件实现图片轮播

    原文:http://www.cnblogs.com/wendingding/p/3763527.html iOS开发UI篇—UIScrollView控件实现图片轮播 一.实现效果 实现图片的自动轮播 ...

  9. ios开发中关闭textview控件的虚拟键盘

    在ios开发中,textfield控件在点击的时候出现虚拟键盘,关掉虚拟键盘可以通过虚拟键盘中的done button和点击view中的任意地方来关闭虚拟键盘. 1.第一种方法是textfield控件 ...

随机推荐

  1. HttpServletRequest 类

    目录 HttpServletRequest类有什么作用 HttpServletRequest 类的常用方法 如何获取请求参数 doGet 请求的中文乱码解决: POST 请求的中文乱码解决 请求的转发 ...

  2. DolphinScheduler 1.2.0 源码解析之 MasterServer

    这一篇主要讲解的是dolphinscheduler 1.2.0 的master部分的源码,从主类MasterServer开始,从启动到运行,master主要做了以下三件事情 Zookeeper 节点初 ...

  3. 百亿数据百亿花, 库若恒河沙复沙,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang数据库操作实践EP12

    Golang可以通过Gorm包来操作数据库,所谓ORM,即Object Relational Mapping(数据关系映射),说白了就是通过模式化的语法来操作数据库的行对象或者表对象,对比相对灵活繁复 ...

  4. LeetCode 593. 有效的正方形(向量做法)

    题目 题目链接:593. 有效的正方形 题意:给出二维平面上四个点的坐标,判断这四个点是否能构成一个正方形,四个点的输入顺序不做任何保证. 思路 通过向量运算可以很轻松地解决这道题.任取一点向其他三点 ...

  5. Java项目生成电脑桌面快捷脚本

    一.场景说明 经常需要查询以及设置手机验证码,一般验证码都是放在Redis,为了节省短信费,可以直接设置Redis,本篇内容主要介绍如何便捷查询和设置手机验证码,非开发人员也会操作. 二.Java代码 ...

  6. 【Java】idea同时运行多个一样的类

    点击"Edit Configurations..." 在左侧选中需要重复运行的类 单击"Modify options" 选择"Allow multip ...

  7. Codeforces Round #606(B-D)

    Dashboard - Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) - Codeforces ...

  8. Kingbase V8R6集群安装部署案例---脚本在线一键扩容

    案例说明: KingbaseES V8R6支持图形化方式在线扩容,但是在一些生产环境,在服务器不支持图形化界面的情况下 ,只能通过脚本命令行的方式执行集群的部署或在线扩容. Tips: Kingbas ...

  9. 01-MyBatisPlus简介

    一.简介 官网:http://mp.baomidou.com/ 参考教程:https://baomidou.com/pages/24112f/ MyBatis-Plus(简称 MP)是一个 MyBat ...

  10. 基于electron+vue+element构建项目模板之【创建项目篇】

    1.概述 electron:使用javascript.css.html构建跨平台的桌面应用程序 vue:数据驱动视图中的一款渐进式的javascript框架 element:基于vue的桌面端UI组件 ...