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

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

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

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

    //MARK: - Calendar//按照苹果的习惯,周日放在第一位let weekdayForDisplay = ["周日","周一","周二","周三","周四","周五","周六"]//获取周 周日:1 - 周六:7func 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的时候是UTCfunc getLastDay(var year:Int,var month:Int) -> Int?{let dateFormatter:NSDateFormatter = NSDateFormatter();dateFormatter.dateFormat = "yyyy/MM/dd";if month == 12 {month = 0year++}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.Centerlet 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事件的属性获得点击位置,根据位置得知被按下的区域隶属于哪个日子。

    //记录每天的格子的Rectvar DayRect = [Int:CGRect]()override func touchesBegan(touches: Set<UITouch>, 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@IBDesignable
class CalendarView: UIView {//MARK: - Inspectable
    @IBInspectablevar CurrentYear : Int = 2015{didSet{if self.CurrentYear < 0 {self.CurrentYear = 2015}setNeedsDisplay()}}@IBInspectablevar CurrentMonth : Int = 10 {didSet{if self.CurrentMonth < 0 || self.CurrentMonth > 12 {self.CurrentMonth = 1}setNeedsDisplay()}}@IBInspectablevar padding : CGFloat = 4 {didSet{if (self.padding > 50 ) {self.padding = 50}setNeedsDisplay()}}@IBInspectablevar mergin : CGFloat = 4 {didSet{if (self.mergin > 50 ) {self.mergin = 50}setNeedsDisplay()}}@IBInspectablevar RowHeight : CGFloat = 20{didSet{if (self.RowHeight > 100 ) {self.RowHeight = 100}setNeedsDisplay()}}@IBInspectablevar 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 - 周六:7func 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的时候是UTCfunc getLastDay(var year:Int,var month:Int) -> Int?{let dateFormatter:NSDateFormatter = NSDateFormatter();dateFormatter.dateFormat = "yyyy/MM/dd";if month == 12 {month = 0year++}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//记录每天的格子的Rectvar DayRect = [Int:CGRect]()override func touchesBegan(touches: Set<UITouch>, 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//查资料可知默认字体为12let NSDefaultFontSize : CGFloat = 12;//绘制表头let UseableWidth :CGFloat = rect.width - (padding + mergin) * 2;let WeekdayColumnWidth : CGFloat = UseableWidth / 7var leftside  : CGFloat = padding + merginfor 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 + merginlet 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) * WeekdayColumnWidthlet 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

iOs 自定义UIView 日历的实现 Swift2.1相关推荐

  1. ios 自定义UIView绘制时文字上下颠倒问题解决

    - (void)drawRect:(CGRect)rect {     [self showPage:m_currentPageIndex]; } - (void)showPage:(int)page ...

  2. IOS xib和代码自定义UIView

    https://www.jianshu.com/p/1bcc29653085 总结的比较好 iOS开发中,我们常常将一块View封装起来,以便于统一管理内部的子控件. 下面就来说说自定义View的封装 ...

  3. 一劳永逸,iOS 自定义 ActionSheet 封装流程

    原文链接:http://www.jianshu.com/p/cfb87a7db7b1 本文为 iOS 自定义视图封装<一劳永逸>系列的第四期,旨在提供封装思路,结果固然重要,但理解过程才最 ...

  4. iOS自定义View 控件自动计算size能力

    iOS自定义View 控件自动计算size能力 背景 在使用 UILabel 和 UIImage 的时候,不用指定宽高约束,控件也不会报约束缺失,还可以根据内容自己确定适合的宽高,特别适合 Xib 和 ...

  5. ios 自定义字体_如何仅用几行代码在iOS应用中创建一致的自定义字体

    ios 自定义字体 by Yuichi Fujiki 藤木雄一 In this article, you'll learn how to create a unified custom look th ...

  6. iOS自定义组与组之间的距离以及视图

    iOS自定义组与组之间的距离以及视图 //头视图高度 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(N ...

  7. iOS 自定义layer的两种方式

    在iOS中,你能看得见摸得着的东西基本都是UIView,比如一个按钮,一个标签,一个文本输入框,这些都是UIView: 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层 在创建UIVi ...

  8. iOS 自定义转场动画浅谈

    代码地址如下: http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差 ...

  9. php使用自定义alert,IOS_iOS自定义alertView提示框实例分享,本文实例为大家分享iOS自定义a - phpStudy...

    iOS自定义alertView提示框实例分享 本文实例为大家分享iOS自定义alertView提示框,先上图,弹框的背景色,按钮背景色,提示的消息的字体颜色都可以改变 利用单例实现丰富的自定义接口 / ...

最新文章

  1. 李飞飞下半年或将从 Google离职?李飞飞回应
  2. Ocelot(一)- .Net Core开源网关
  3. 由浅入深laravel教程 :中间件
  4. Scrapy爬取整个美女网爬下来,要多少有多少
  5. PostMan入门使用教程
  6. 如何解决ado.net entity framework的使用,再别的调用项目中依然正常
  7. 使用ANT编译项目报错 com.sun.image.codec.jpeg does not exist 解决方法
  8. HCIE Secuirty 防火墙内容安全组合 备考笔记(幕布)
  9. runtime 的 assemblyIdentity 元素和bindingRedirect 元素
  10. 【网址收藏】golang持久层框架GORM 中文文档地址
  11. qt在linux下编译资源文件,linux下Qt qrc文件的编写与应用
  12. 计算机中央控制单元是由什么组成,电子控制单元由什么组成
  13. 在Ubuntu中使用Tomcat的小tips_codestorm_新浪博客
  14. c语言判断非法字符题目,C语言考试题库之判断题-c语言考试判断题
  15. python3 psycopg2查询PostgreSQL返回字典
  16. 微软 Windows 10 v2004 最新官方 ISO 镜像
  17. android 群控 网络 adb,逍遥安卓模拟器群控源码
  18. Halcon 连接 pointgrey 双目相机
  19. 电商数据分析--流程、方法
  20. scrapy框架开发爬虫实战——css语法

热门文章

  1. 机器学习之单变量线性回归
  2. SAP QA32 做使用决策系统报错:分类数据的不一致性=交易终止
  3. 人工智能再升温:零售行业如何抢占AI先机
  4. 2020五大技术趋势一览!超自动化、人类增强技术、无人驾驶发展、机器视觉崛起、区块链实用化...
  5. 全球数字孪生市场大预测:2025 年的 358 亿美元,年复合增长率(CAGR)高达 37.8%...
  6. 5个层级带你看清一颗芯片的内部结构
  7. 清华大学施路平:发展人工通用智能最好的时机到了!
  8. 测试归测试,自动驾驶向个人全面开放依然长路漫漫
  9. 深度 | 智慧•城市,基于国际视野下的思考
  10. 卷积神经网络为什么能称霸计算机视觉领域?