博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOs 自定义UIView 日历的实现 Swift2.1
阅读量:6716 次
发布时间:2019-06-25

本文共 11060 字,大约阅读时间需要 36 分钟。

学习Swift有一个月了,动手写一个UIView吧。

所有源代码在最后,直接用就可以了,第一次写Swift,和C#,Java还是有区别的

(博客园可以考虑在代码插入中添加Swift的着色了)

1  函数准备。Swift的日历函数,随着版本的变化,变动很大。

 

//MARK: - Calendar    //按照苹果的习惯,周日放在第一位    let weekdayForDisplay = ["周日","周一","周二","周三","周四","周五","周六"]            //获取周 周日:1 - 周六:7    func getWeekDay(year:Int,month:Int,day:Int) ->Int{        let dateFormatter:NSDateFormatter = NSDateFormatter();        dateFormatter.dateFormat = "yyyy/MM/dd";        let date:NSDate? = dateFormatter.dateFromString(String(format:"%04d/%02d/%02d",year,month,day));        if date != nil {            let calendar:NSCalendar = NSCalendar.currentCalendar()            let dateComp:NSDateComponents = calendar.components(NSCalendarUnit.NSWeekdayCalendarUnit, fromDate: date!)            return dateComp.weekday;        }        return 0;    }        //这个月的最后一天    //先获得下个月的第一天,然后在此基础上减去24小时    //注意这里的时间Debug的时候是UTC    func getLastDay(var year:Int,var month:Int) -> Int?{        let dateFormatter:NSDateFormatter = NSDateFormatter();        dateFormatter.dateFormat = "yyyy/MM/dd";        if month == 12 {            month = 0            year++        }        let targetDate:NSDate? = dateFormatter.dateFromString(String(format:"%04d/%02d/01",year,month+1));        if targetDate != nil {                        let orgDate = NSDate(timeInterval:(24*60*60)*(-1), sinceDate: targetDate!)            let str:String = dateFormatter.stringFromDate(orgDate)            return Int((str as NSString).componentsSeparatedByString("/").last!);        }                return nil;    }

下面是NSDateCompents的一个坑,Swift 1 和 Swift 2 写法不一样

let today = NSDate()        let calendar = NSCalendar(identifier: NSGregorianCalendar)        let comps:NSDateComponents = calendar!.components([NSCalendarUnit.Year,NSCalendarUnit.Month,NSCalendarUnit.Day], fromDate: today)

Swift 2 OptionSetType ,比较一下OC和Swift的写法

 

Objective-C

unsigned unitFlags = NSCalendarUnitYear

                   | NSCalendarUnitMonth
                   | NSCalendarUnitDay
                   | NSCalendarUnitWeekday
                   | NSCalendarUnitHour
                   | NSCalendarUnitMinute
                   | NSCalendarUnitSecond;

Swift 2.0

let unitFlags: NSCalendarUnit = [ .Year,

                                  .Month,
                                  .Day,
                                  .Weekday,
                                  .Hour,
                                  .Minute,
                                  .Second ]

Swift 1.2

let unitFlags: NSCalendarUnit = .CalendarUnitYear

                              | .CalendarUnitMonth
                              | .CalendarUnitDay
                              | .CalendarUnitWeekday
                              | .CalendarUnitHour
                              | .CalendarUnitMinute
                              | .CalendarUnitSecond

 

 

Swift2.0 的语法和1.2有区别   OptionSetType

 

2.接下来就是绘图,绘图就是各种被塞尔曲线

重点如下

 

如何居中        let paragraph = NSMutableParagraphStyle()        paragraph.alignment = NSTextAlignment.Center                let text  =  NSMutableAttributedString(string: weekdayForDisplay[i],attributes: [NSParagraphStyleAttributeName: paragraph])        let CellRect = CGRect(x: leftside  , y:padding + mergin, width: WeekdayColumnWidth, height: RowHeight)        text.drawInRect(CellRect)红字粗体        text.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(),range:NSMakeRange(0,text.length))        text.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(NSDefaultFontSize),range:NSMakeRange(0,text.length))

 

3.接下来是如何捕获点击事件

由于是全手工绘制日历的格子,所以,就用OnTouchBegan事件的属性获得点击位置,根据位置得知被按下的区域隶属于哪个日子。

//记录每天的格子的Rect    var DayRect = [Int:CGRect]()            override func touchesBegan(touches: Set
, withEvent event: UIEvent?) { let SignleTouch = touches.first! let Touchpoint = SignleTouch.locationInView(self) let pick = getDayByTouchPoint(Touchpoint) print("TouchPoint : X = \(Touchpoint.x) Y = \(Touchpoint.y) Day: \(pick)") if pick != 0 {self.PickedDay = pick } } //根据触摸点获取日期 func getDayByTouchPoint(touchpoint:CGPoint) -> Int { for day in DayRect{ if day.1.contains(touchpoint){ return day.0 } } return 0 }

 

最终效果如下图,可以实现点击选择日期。整个代码,8个小时可以完成。

现在的问题是,如果选择的日子变化了,我不知道怎么告诉上层的 ViewController,SelectDateChanged。

如果可以的话,最好能够出现 ActionConnection,可以拖曳连线,将Action和代码绑定。谁知道怎么做吗?

////  CalendarView.swift//  PlanAndTarget////  Created by  scs on 15/10/13.//  Copyright © 2015年  scs. All rights reserved.//import UIKit@IBDesignableclass CalendarView: UIView {    //MARK: - Inspectable    @IBInspectable    var CurrentYear : Int = 2015{        didSet{            if self.CurrentYear < 0 {                self.CurrentYear = 2015            }            setNeedsDisplay()        }    }        @IBInspectable    var CurrentMonth : Int = 10 {        didSet{            if self.CurrentMonth < 0 || self.CurrentMonth > 12 {                self.CurrentMonth = 1            }            setNeedsDisplay()        }    }        @IBInspectable    var padding : CGFloat = 4 {        didSet{            if (self.padding > 50 ) {                self.padding = 50            }            setNeedsDisplay()        }    }        @IBInspectable    var mergin : CGFloat = 4 {        didSet{            if (self.mergin > 50 ) {                self.mergin = 50            }            setNeedsDisplay()        }    }        @IBInspectable    var RowHeight : CGFloat = 20{        didSet{            if (self.RowHeight > 100 ) {                self.RowHeight = 100            }            setNeedsDisplay()        }    }        @IBInspectable    var PickedDay : Int = 1 {        didSet{            if (self.PickedDay < 0){                self.PickedDay = 1            }            let lastDay = getLastDay( CurrentYear, month: CurrentMonth)            if (self.PickedDay > lastDay!){                self.PickedDay = lastDay!            }            setNeedsDisplay()        }    }                    //MARK: - Calendar    //按照苹果的习惯,周日放在第一位    let weekdayForDisplay = ["周日","周一","周二","周三","周四","周五","周六"]            //获取周 周日:1 - 周六:7    func getWeekDay(year:Int,month:Int,day:Int) ->Int{        let dateFormatter:NSDateFormatter = NSDateFormatter();        dateFormatter.dateFormat = "yyyy/MM/dd";        let date:NSDate? = dateFormatter.dateFromString(String(format:"%04d/%02d/%02d",year,month,day));        if date != nil {            let calendar:NSCalendar = NSCalendar.currentCalendar()            let dateComp:NSDateComponents = calendar.components(NSCalendarUnit.NSWeekdayCalendarUnit, fromDate: date!)            return dateComp.weekday;        }        return 0;    }        //这个月的最后一天    //先获得下个月的第一天,然后在此基础上减去24小时    //注意这里的时间Debug的时候是UTC    func getLastDay(var year:Int,var month:Int) -> Int?{        let dateFormatter:NSDateFormatter = NSDateFormatter();        dateFormatter.dateFormat = "yyyy/MM/dd";        if month == 12 {            month = 0            year++        }        let targetDate:NSDate? = dateFormatter.dateFromString(String(format:"%04d/%02d/01",year,month+1));        if targetDate != nil {                        let orgDate = NSDate(timeInterval:(24*60*60)*(-1), sinceDate: targetDate!)            let str:String = dateFormatter.stringFromDate(orgDate)            return Int((str as NSString).componentsSeparatedByString("/").last!);        }                return nil;    }        //MARK: - Event    //记录每天的格子的Rect    var DayRect = [Int:CGRect]()            override func touchesBegan(touches: Set
, withEvent event: UIEvent?) { let SignleTouch = touches.first! let Touchpoint = SignleTouch.locationInView(self) let pick = getDayByTouchPoint(Touchpoint) print("TouchPoint : X = \(Touchpoint.x) Y = \(Touchpoint.y) Day: \(pick)") if pick != 0 {self.PickedDay = pick } } //根据触摸点获取日期 func getDayByTouchPoint(touchpoint:CGPoint) -> Int { for day in DayRect{ if day.1.contains(touchpoint){ return day.0 } } return 0 } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func drawRect(rect: CGRect) { let paragraph = NSMutableParagraphStyle() paragraph.alignment = NSTextAlignment.Center //查资料可知默认字体为12 let NSDefaultFontSize : CGFloat = 12; //绘制表头 let UseableWidth :CGFloat = rect.width - (padding + mergin) * 2; let WeekdayColumnWidth : CGFloat = UseableWidth / 7 var leftside : CGFloat = padding + mergin for i in 0...6{ let text = NSMutableAttributedString(string: weekdayForDisplay[i],attributes: [NSParagraphStyleAttributeName: paragraph]) let CellRect = CGRect(x: leftside , y:padding + mergin, width: WeekdayColumnWidth, height: RowHeight) text.drawInRect(CellRect) leftside += WeekdayColumnWidth } //绘制当月每天 var rowCount = 1; leftside = padding + mergin let today = NSDate() let calendar = NSCalendar(identifier: NSGregorianCalendar) let comps:NSDateComponents = calendar!.components([NSCalendarUnit.Year,NSCalendarUnit.Month,NSCalendarUnit.Day], fromDate: today) //Clear DayRect.removeAll() for day in 1...getLastDay(CurrentYear,month:CurrentMonth)!{ let weekday = getWeekDay(CurrentYear, month: CurrentMonth, day: day) let text = NSMutableAttributedString(string: String(day), attributes: [NSParagraphStyleAttributeName: paragraph]) let LeftTopX = leftside + CGFloat(weekday - 1) * WeekdayColumnWidth let LeftTopY = padding + mergin + RowHeight * CGFloat(rowCount) let CellRect :CGRect = CGRect(x: LeftTopX, y: LeftTopY, width: WeekdayColumnWidth, height: RowHeight) if (PickedDay == day){ //选中的日子,UI效果 let PickRectPath = UIBezierPath(roundedRect: CellRect, cornerRadius: RowHeight/2) UIColor.blueColor().colorWithAlphaComponent(0.3).setFill() PickRectPath.fill() } if (comps.year == CurrentYear && comps.month == CurrentMonth && comps.day == day){ text.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(),range:NSMakeRange(0,text.length)) text.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(NSDefaultFontSize),range:NSMakeRange(0,text.length)) } text.drawInRect(CellRect) DayRect[day] = CellRect //绘制了周日之后,需要新的一行 if weekday == 7 { rowCount++ } } //绘制外框 let path : UIBezierPath = UIBezierPath(rect: CGRect(x: padding, y: padding, width: rect.width - padding * 2 , height: padding + mergin + RowHeight * CGFloat(rowCount - 1) + 10 )) path.stroke() //path = UIBezierPath(rect: CGRect(x: padding + mergin, y: padding + mergin, width: rect.width - (padding + mergin) * 2 , height: rect.height - (padding + mergin) * 2)) //path.stroke() print("LastDay Of 2015/10 : \(getLastDay(CurrentYear, month: CurrentMonth))" ) print("2015/10/18 : \(weekdayForDisplay[getWeekDay(CurrentYear, month: CurrentMonth, day: 18) - 1] )" ) print("Calendar Size Height: \(rect.height) Width: \(rect.width)" ) } }

 

转载于:https://www.cnblogs.com/TextEditor/p/4877163.html

你可能感兴趣的文章
Cisco网络设备安全管理和报告
查看>>
七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理
查看>>
将组策略应用到满足条件的计算机---配置组策略筛选
查看>>
PHP中的$this和$that指针使用案例
查看>>
SQL Server 2012 内存计数器的变化
查看>>
ubuntu无法修改ROOT密码的问题解决
查看>>
老男孩linux培训某节课前考试试题及答案分享
查看>>
Rsync镜像同步工具的安装配置
查看>>
logstash日志系统搭建
查看>>
通过Dmidecode读取硬件信息。
查看>>
DPM2012系列之六:在Win7上安装DPM远程管理控制台
查看>>
SCOM 2012知识分享-19:配置数据库整理设置
查看>>
鸟哥?马哥?靠边站!今天猫哥带你玩千万PV级别运维架构实战
查看>>
欢迎加入Java私活外包QQ群
查看>>
Python风靡全宇宙,首要原因是它?
查看>>
Win7部署基础知识(8):使用WDS捕获与应用映像
查看>>
企业云桌面-14-将vCenter 6.5证书导入-受信任人-企业
查看>>
Python从菜鸟到高手(13):分片(Slicing)
查看>>
实战操作百度文库、百度经验营销,让您的“流量”稳居首页
查看>>
KMS激活服务器inactivity exceeded threshold警报处理
查看>>