首页 > 其他分享 >iOS开发之自定义日历控件

iOS开发之自定义日历控件

时间:2022-10-24 17:26:04浏览次数:88  
标签:case 控件 自定义 日历 iOS let newDate

前言

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

效果

效果图

功能

原理

层次结构使用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的界面布局

标签:case,控件,自定义,日历,iOS,let,newDate
From: https://www.cnblogs.com/JmoVxia/p/16822128.html

相关文章

  • 自定义注解
    1.定义某个方法的注解@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfaceMethodsListener{}MethodsListener这个名......
  • 记录--分享8个非常实用的Vue自定义指令
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助在Vue,除了核心功能默认内置的指令(v-model和v-show),Vue也允许注册自定义指令。它的作用价值在于当......
  • Selenium4Web自动化7-文件上传和日期控件
    一、文件上传操作-input标签文件选择当input元素为文件类型时,文件上传对话框可以使用Selenium处理.文件上传的代码实现如下fromseleniumimportwebdriverfromwebd......
  • cmap 自定义颜色卡
    #渐变色cmap=LinearSegmentedColormap.from_list('white_to_red',['#00FF00','#0000FF','#FFFF00','#FF0000'])#间隔色块cmap=mpl.colors.ListedColormap([......
  • 服务端自定义生成PDF的几种方案
    一、itext表单填充使用方式:itext表单填充方案是以pdf作为基础模板,通过在pdf中嵌入表单元素组件的方式(需要使用pdf编辑工具),最后由程序进行数据填充并另存为pdf结果。方案优......
  • pg_basebackup备份(无自定义表空间)
    环境:OS:Centos7DB:13.81.直接备份需要提前创建好备份目录su-postgres[postgres@host134pg_backup]$mkdir-p/tmp/pg_backup/[postgres@host134pg_backup]$pg_bas......
  • dremio kernel 模块之DremioSqlDialect
    参考图实际上是继承自calcite的sql方言类  arp扩展的说明目前官方的arp主要是对于sql数据库类型的高级支持,当然需要依赖社区版的arp公共包dremio-ce-jdbc-pluginar......
  • SAP UI5 的 TimePicker ,一个钟表外观的时间选择控件试读版
    一套适合SAPUI5初学者循序渐进的学习教程本专栏计划的文章数在​​300​​​篇左右,到​​2022年10月14日​​​为止,目前已经更新了​​141​​​篇,专栏完成度为​......
  • C语言——自定义类型(结构体+枚举+联合)
    结构体基础知识结构是一些值的集合,这些值被称为成员变量;结构体可以存储不同类型的数据项,而数组中是存储相同类型数据项声明structtag{//struct是关键字,tag是结构体标签名......
  • Vue+vite+ts+axios+element plus
    一、介绍vueviteTypeScriptScssElementPlusRouteaxiosVuex二、步骤2.1、创建项目使用Vite快速构建项目Vite是一种新型前端构建工具,能够显著提升前端开......