iOS 日历控件
近期需要写一个交互有点DT的日历控件,具体交互细节这里略过不表。
不过再怎么复杂的控件,也是由基础的零配件组装起来的,这里最基本的就是日历控件。
先上图:
从图中可以看出日历控件就是由一个个小方块组成的,每一行有7个小方块,分别表示一周的星期天到星期六。
给定一个月份,我们首先需要知道这个月有多少周。那么如何确定一个月有多少周呢?
我是这么想的,在NSDate上做扩展:
- @interface NSDate (WQCalendarLogic)
0. 首先需要知道这个月有多少天:
- - (NSUInteger)numberOfDaysInCurrentMonth
- {
- // 频繁调用 [NSCalendar currentCalendar] 可能存在性能问题
- return [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:self].length;
- }
1. 确定这个月的第一天是星期几。这样就能知道给定月份的第一周有几天:
- - (NSDate *)firstDayOfCurrentMonth
- {
- NSDate *startDate = nil;
- BOOL ok = [[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startDate interval:NULL forDate:self];
- NSAssert1(ok, @"Failed to calculate the first day of the month based on %@", self);
- return startDate;
- }
- - (NSUInteger)weeklyOrdinality
- {
- return [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit:NSWeekCalendarUnit forDate:self];
- }
2. 减去第一周的天数,剩余天数除以7,得到倍数和余数:
- - (NSUInteger)numberOfWeeksInCurrentMonth
- {
- NSUInteger weekday = [[self firstDayOfCurrentMonth] weeklyOrdinality];
- NSUInteger days = [self numberOfDaysInCurrentMonth];
- NSUInteger weeks = 0;
- if (weekday > 1) {
- weeks += 1, days -= (7 - weekday + 1);
- }
- weeks += days / 7;
- weeks += (days % 7 > 0) ? 1 : 0;
- return weeks;
- }
到这里,就可以知道一个月有多少行多少列,从而计算出需要多少个小方块来展示:
- @interface WQCalendarTileView : UIView
这些小方块用一个大方块来承载:
- @interface WQCalendarGridView : UIView
- @property (nonatomic, weak) id<WQCalendarGridViewDataSource> dataSource;
- @property (nonatomic, weak) id<WQCalendarGridViewDelegate> delegate;
- - (void)reloadData;
和UITableView类似,当WQCalendarGridView调用reloadData接口时,会开始进行布局。而布局所需要的信息由dataSource和delegate提供:
- @class WQCalendarGridView;
- @protocol WQCalendarGridViewDataSource <NSObject>
- @required
- - (NSUInteger)numberOfRowsInGridView:(WQCalendarGridView *)gridView;
- - (WQCalendarTileView *)gridView:(WQCalendarGridView *)gridView tileViewForRow:(NSUInteger)row column:(NSUInteger)column;
- @optional
- - (CGFloat)heightForRowInGridView:(WQCalendarGridView *)gridView;
- @end
- @protocol WQCalendarGridViewDelegate <NSObject>
- - (void)gridView:(WQCalendarGridView *)gridView didSelectAtRow:(NSUInteger)row column:(NSUInteger)column;
- @end
每一行的高度,heightForRow,我比较倾向于由dataSource提供 :)
第一个dataSource方法上面已经可以计算出来了,第二个dataSource方法需要对每一个tile进行配置,比如非当前月的以灰色展示,那么我们就需要知道当前月展示中包含的 上个月残留部分,和 下个月的开头部分:
- #pragma mark - method to calculate days in previous, current and the following month.
- - (void)calculateDaysInPreviousMonthWithDate:(NSDate *)date
- {
- NSUInteger weeklyOrdinality = [[date firstDayOfCurrentMonth] weeklyOrdinality];
- NSDate *dayInThePreviousMonth = [date dayInThePreviousMonth];
- NSUInteger daysCount = [dayInThePreviousMonth numberOfDaysInCurrentMonth];
- NSUInteger partialDaysCount = weeklyOrdinality - 1;
- NSDateComponents *components = [dayInThePreviousMonth YMDComponents];
- self.daysInPreviousMonth = [NSMutableArray arrayWithCapacity:partialDaysCount];
- for (int i = daysCount - partialDaysCount + 1; i < daysCount + 1; ++i) {
- WQCalendarDay *calendarDay = [WQCalendarDay calendarDayWithYear:components.year month:components.month day:i];
- [self.daysInPreviousMonth addObject:calendarDay];
- [self.calendarDays addObject:calendarDay];
- }
- }
- - (void)calculateDaysInCurrentMonthWithDate:(NSDate *)date
- {
- NSUInteger daysCount = [date numberOfDaysInCurrentMonth];
- NSDateComponents *components = [date YMDComponents];
- self.daysInCurrentMonth = [NSMutableArray arrayWithCapacity:daysCount];
- for (int i = 1; i < daysCount + 1; ++i) {
- WQCalendarDay *calendarDay = [WQCalendarDay calendarDayWithYear:components.year month:components.month day:i];
- [self.daysInCurrentMonth addObject:calendarDay];
- [self.calendarDays addObject:calendarDay];
- }
- }
- - (void)calculateDaysInFollowingMonthWithDate:(NSDate *)date
- {
- NSUInteger weeklyOrdinality = [[date lastDayOfCurrentMonth] weeklyOrdinality];
- if (weeklyOrdinality == 7) return ;
- NSUInteger partialDaysCount = 7 - weeklyOrdinality;
- NSDateComponents *components = [[date dayInTheFollowingMonth] YMDComponents];
- self.daysInFollowingMonth = [NSMutableArray arrayWithCapacity:partialDaysCount];
- for (int i = 1; i < partialDaysCount + 1; ++i) {
- WQCalendarDay *calendarDay = [WQCalendarDay calendarDayWithYear:components.year month:components.month day:i];
- [self.daysInFollowingMonth addObject:calendarDay];
- [self.calendarDays addObject:calendarDay];
- }
- }
到此,就可以顺利地展现出给定月份的日历控件了。最近项目比较忙,随手记一篇 :)
copy from http://blog.csdn.net/jasonblog/article/details/21977481
iOS 日历控件的更多相关文章
- iOS日历控件
项目需要,前一阵子重构了下iPad工程,添加了一个滚动无缝日历. 当时没有头绪,网上找了一个源码改吧改吧就上线了(参考链接),这个功能很多而且流畅性也特别好,推荐不会写的可以参考下. 这几天,活不太忙 ...
- iOS开发之自定义日历控件
前言 日常开发中经常会遇到日期选择,为了方便使用,简单封装了一个日历控件,在此抛砖引玉供大家参考. 效果 功能 支持单选.区间 支持默认选中日期 支持限制月份 支持过去.当前.未来模式 支持frame ...
- IOS自定义日历控件的简单实现(附思想及过程)
因为程序要求要插入一个日历控件,该空间的要求是从当天开始及以后的六个月内的日历,上网查资料基本上都说只要获取两个条件(当月第一天周几和本月一共有多少天)就可以实现一个简单的日历,剩下的靠自己的简单逻辑 ...
- 在iOS上实现一个简单的日历控件
http://blog.csdn.net/jasonblog/article/details/21977481 近期需要写一个交互有点DT的日历控件,具体交互细节这里略过不表. 不过再怎么复杂的控件, ...
- android日历控件(一)
自定义日历并且具备设置今天以前的时间不可点选,以前的颜色和当前的颜色不同,以及获取两次点击日期之间间隔的天数所以说细节比较多 个人习惯,先上图 靠,笔记本不知道怎么回事,禁用到触摸板之后 再次唤醒屏幕 ...
- JS调用Android、Ios原生控件
在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...
- 初识IOS,Label控件的应用。
初识IOS,Label控件的应用. // // ViewController.m // Gua.test // // Created by 郭美男 on 16/5/31. // Copyright © ...
- JQuery日历控件
日历控件最后一弹——JQuery实现,换汤不换药.原理一模一样,换了种实现工具.关于日历的终于写完了,接下来研究研究nodejs.嗯,近期就这点事了. 同样还是将input的id设置成calendar ...
- 【转】【WebDriver】不可编辑域和日历控件域的输入 javascript
http://blog.csdn.net/fudax/article/details/8089404 今天用到日历控件,用第一个javascript执行后页面上的日期控件后,在html中可以看到生效日 ...
随机推荐
- servlet三种实现方式之三通过继承HttpServlet开发servlet
servlet有三种实现方式: 1.实现servlet接口 2.继承GenericServlet 3.通过继承HttpServlet开发servlet 第三种: import java.io.*; i ...
- What I Have Lived For(我为什么而活着-罗素)
What I Have Lived For by Bertrand Russell Three passions, simple but overwhelmingly strong, have gov ...
- 发生了Post错误:错误代码40005,微信返回错误信息:invalid file type
给客户部署 PxxCms, 使用群发功能发送图文的的时候提示: 发生了Post错误:错误代码40005,微信返回错误信息:invalid file type, 没学过php伤不起 ... Google ...
- Oracle 11g透明网关连接Sqlserver 2000
一.环境 公司网站系统使用的是IIS + Oracle 但公司某系统使用的是Sqlserver 2000, 但其数据需要做成报表放到网站上,为简化编程,使用Oracle做透明网关,定期从Sqlserv ...
- CPU卡
CPU卡芯片通俗地讲就是指芯片内含有一个微处理器,它的功能相当于一台微型计算机.人们经常使用的集成电路卡(IC卡)上的金属片就是CPU卡芯片.CPU卡可适用于金融.保险.交警.政府行业等多个领域,具有 ...
- JAVA GUI学习 - JOptionPane对话框组件学习
/** * 对话框 - 学习笔记 * @author Wfei * */ public class JoptionPaneKnow extends JFrame { public JoptionPan ...
- Gimp制作圆角透明图片
用蒙版制作圆角透明图片,步骤如下: 1,用Gimp(2.8版本)打开图片 2,在图层窗口右键当前图层创建蒙版 3,选择蒙版类型黑色(全透明) 4,结果如下 5,用圆角矩形选择工具选择图片,设置圆角半径 ...
- poj 3026 Borg Maze bfs建图+最小生成树
题目说从S开始,在S或者A的地方可以分裂前进. 想一想后发现就是求一颗最小生成树. 首先bfs预处理得到每两点之间的距离,我的程序用map做了一个映射,将每个点的坐标映射到1-n上,这样建图比较方便. ...
- Android中GPS简介及其应用
GPS是Global Positioning System(全球定位系统)的简称,它的作用就是为全球的物体提供定位功能.GPS定位是一门高新技术,但对于Android程序员来说,开发GPS功能的应用程 ...
- 重启IIS报错:IIS 服务或万维网发布服务,或者依赖这 服务可能在启动期间发生错误或者已禁用
参考文章: http://www.cnblogs.com/zengen/archive/2010/10/29/1864569.html 开启如下服务: Net.Msmq Listener Adapte ...