前言日常开发中经常会遇到日期选择,为了方便使用,简单封装了一个日历控件,在此抛砖引玉供大家参考 。
效果
![iOS开发之自定义日历控件](http://img.zhejianglong.com/231018/2211515133-0.png)
文章插图
功能
- 支持单选、区间
- 支持默认选中日期
- 支持限制月份
- 支持过去、当前、未来模式
- 支持
frame
、AutoLayout
UIStackView
布局,UICollectionView
复用,背景使用DecorationView
。核心代码日历核心代码在于计算每个月的日期,主要代码如下:
func month() -> [CLCalendarMonthModel] {func day(with date: Date, section: Int) -> [CLCalendarDayModel] {var newDate = datelet tatalDay = newDate.daysInMonthlet 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.daysif 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 = https://www.huyubaike.com/biancheng/0if config.type == .past {value = config.limitMonth - 1} else if config.type == .today {value = config.limitMonth / 2}return value}()let start = todayDate - month.monthsfor i in 0 ..< config.limitMonth {let date = start + i.monthslet 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 pastcase todaycase future}enum CLSelectType {case singlecase 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: Int64init(rawValue: Int64) {self.rawValue = https://www.huyubaike.com/biancheng/rawValue}}struct CLColor {var background ="#ffffff".uiColorvar topToolBackground = "#F4F4F4".uiColorvar topToolText = "#444444".uiColorvar topToolTextWeekend = "#3CCA79".uiColorvar sectionBackgroundText = "f2f2f2".uiColorvar selectStartBackground = "#4bce817f".uiColorvar selectBackground = "#afe9c77f".uiColorvar selectEndBackground = "#4bce817f".uiColorvar todayText = "#32cd32".uiColorvar titleText = "#555555".uiColorvar subtitleText = "#555555".uiColorvar selectTodayText = "#32cd32".uiColorvar selectTitleText = "#ffffff".uiColorvar selectSubtitleText = "#ffffff".uiColorvar failureTitleText = "#a9a9a9".uiColorvar failureSubtitleText = "#a9a9a9".uiColorvar failureBackground = "#dcdcdc32".uiColor}var color = CLColor()var selectBegin: Date?var selectEnd: Date?var limitMonth = 12var type = CLCalendarType.todayvar selectType = CLSelectType.areavar touchType: CLTouchType = [.today, .past]var isShowLunarCalendar = truevar insetsLayoutMarginsFromSafeArea = truevar headerHight = 50.0}
总结定制化开发请自行参考CLDemo修改,如果喜欢,欢迎star 。参考资料
- DateToolsSwift
- UICollectionView:装饰视图 Decoration View
- 使用UIStackView来简化iOS的界面布局
推荐阅读
- Windows10 + Eclipse C/C++开发环境配置极简教程
- 元气骑士幸运局怎么开启
- apple watch series 7开箱_开箱评测
- linux下开机启动443程序无法访问解决方法
- 小米11一亿像素怎么调_小米11一亿像素怎么打开
- ios 15正式版什么时候出_ios15什么时候正式上线
- 梦幻西游单开赚钱攻略详细(梦幻3个号摆摊月入5000)
- 听说玩梦幻西游能赚钱,小白如何开始(梦幻单开159能赚钱吗)
- 小小蚁国新手开局怎么发展
- 为什么说:保险柜没有钥匙时,只用笔帽就可以打开怎么做到的