前一段时间因为工作需要实现了一个可以签到的日历,来记录一下实现的思路
效果如图:
 
这里的基本需求是:
1,显示用户某个月的签到情况,已经签到的日子打个圈,没有签到且在某个时间范围内的可以签到,其他的只能看。
2,服务器只会返回这个月用户签到日子的时间戳数组和可以签到的时间范围,剩下的日子就是没有签到的。
3,显示跟普通的日历一样即可,上面是“一二三四五六日”,下面是对应的日期。
4,可以切换到当前日期之前的月份。
 
根据需求,基本思路是:
用一个pageViewController作为基本控制器,控制显示某月签到情况的viewController;
(为什么用pageViewController呢?因为需求要求可以切换月份,用pageViewController方便复用,而且每个月可能都需要请求服务器数据,将网络请求写到viewController当中更好控制整个生命周期)
每个viewController是一个月的情况,上面放一个自定义的calendarView,
用UICollectionView实现CalendarView,每个cell显示一天日期,
定义几个状态分别表示可签到,不可签到,已签到等状态,然后配置好cell的状态就行了。
 
界面的设计大概就是这个样子,难点是日历的逻辑和数据配置问题
 
首先,要根据服务器返回的时间戳确定今天的日期及当月的DateComponents(防止用户修改系统时间来作弊,用NSDateComponents表示某个月方便比较);
然后,根据当月的dateComponents显示日历,
这里需要注意的是,要想办法获取到当月有多少天和当月的第一天是星期几!!!
       获取当月第一天的dateComponents:
    NSDateComponents *firstDayComponents = [[NSDateComponents alloc] init];
    firstDayComponents.year = monthComponents.year;
    firstDayComponents.month = monthComponents.month;
    firstDayComponents.day = 1;
 
然后就可以用NSCalendar的api提供的方法
    NSDate *firstDay = [self.calendar dateFromComponents:firstDayComponents];
    NSDateComponents *dateComponents = [self.calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday fromDate:firstDay];
    NSRange range = [self.calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:firstDay];//指定日期的day在month中的位置
所以range的length就是当月有多少天,dateComponents.weekday就是当月第一天是周几。
这里又需要注意,NSCalendar的firstWeekday和minimumDaysInFirstWeek属性:
- (NSCalendar *)calendar {
    if (!_calendar) {
        _calendar = [NSCalendar currentCalendar];
        _calendar.firstWeekday = 2;//1是周日,2是周一,以此类推
        _calendar.minimumDaysInFirstWeek = 1;//表示一个月的最初一周如果少于这个值,则算为上个月的最后一周,大约等于则算本月第一周,用1就好
    }
    return _calendar;
}
 
有了这些就可以算出当月第一天之前有多少空白cell:
    self.frontBlankCount  = dateComponents.weekday - self.calendar.firstWeekday;
    if (self.frontBlankCount  < 0) {
        //这里,因为weekday周日是1,所以判断下
        self.frontBlankCount  += 7;
    }
然后算出当月最后有多少空白:
    for (int i = 0; i < self.frontBlankCount; i++) {
        //这里是让每个月最开始的地方按需求空白
        [self.dataArray addObject:@""];
    }
    for (int i = 0; i < range.length; i++) {
        NSString *text = [NSString stringWithFormat:@"%@", @(i + 1)];
        [self.dataArray addObject:text];
    }
   
    NSInteger weeks = 0; //每个月有几周
    NSInteger aaa = self.dataArray.count / 7;
    NSInteger bbb = self.dataArray.count % 7;
    if (bbb == 0) {
        weeks = aaa;
    } else {
        weeks = aaa + 1;
    }
    self.backBlankCount = weeks * 7 - self.dataArray.count;
到这里日历就可以完整的显示出来了。
 
剩下的就是匹配签到数据:
只需要一个for循环,判断日历日期是否在服务器返回的签到日期之中就可以了;
如果需要判断是否可以签到,加入一个时间戳大小的判断就行。
最后再reloadData就可以了~~~
 

用NSCalendar和UICollectionView自定义日历,并实现签到显示的更多相关文章

  1. 使用 UICollectionView 实现日历签到功能

    概述 在 App 中,日历通常与签到功能结合使用.是提高用户活跃度的一种方式,同时,签到数据中蕴含了丰富的极其有价值的信息.下面我们就来看看如何在 App 中实现日历签到功能. 效果图 ..... 思 ...

  2. javascript实例学习之六—自定义日历控件

    基于之前上篇博客轻量级jquery,tool.js和base.js.自定义开发的base_datePicker插件,效果类似于jquery_ui的datePicker插件 //基于Base.js以及t ...

  3. 用AJAX自定义日历

    需求分析 在一些购物网站中,都会有促销活动,这些活动都在日历上标注出来,如何通过Ajax让日历 通过读取数据库中的信息,正确的把促销活动标注在日历上,本文通过自定义日历来实现这 个问题. 技术难点 日 ...

  4. Android自定义日历控件(继承系统控件实现)

    Android自定义日历控件(继承系统控件实现) 主要步骤 编写布局 继承LinearLayout设置子控件 设置数据 继承TextView实现有圆圈背景的TextView 添加Attribute 添 ...

  5. Bootstrap-table自定义可编辑每页显示记录数

    写在前面: 最近在做的person功能,由于后期系统中person人数较多,不利用查找person,故需求方将要求可以自己编辑每页显示的数目,而不是固定的写死每页显示的数目. 下面先来看下bootsr ...

  6. IOS自定义日历控件的简单实现(附思想及过程)

    因为程序要求要插入一个日历控件,该空间的要求是从当天开始及以后的六个月内的日历,上网查资料基本上都说只要获取两个条件(当月第一天周几和本月一共有多少天)就可以实现一个简单的日历,剩下的靠自己的简单逻辑 ...

  7. ExtJS基础知识总结:自定义日历和ComboBox控件(二)

    概述 1.ExtJS 5不支持日期选择框中只选择年月,为了满足ExtJs5可以实现选择年月的功能,查询网上资料,整理出来了相应的处理方式,最终实现的效果如下图: 2.ExtJS 控件丰富,如果需要实现 ...

  8. iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流

    上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewControlle ...

  9. UICollectionView 自定义组头组尾的XIB方法

    UICollectionView的加载方式和Tableview很像,基本上加载的方法都差不多,尤其是它的数据源的方法和代理方法基本上类似,只不过是名字上有点细微的差别而已.这里面不赘述. 1. UIC ...

随机推荐

  1. 绿色版的Linux.NET——“Jws.Mono”

    Linux.NET环境的搭建,不仅是一项比较耗时的事情,同时也是一项略显复杂繁琐的事情.特别是对于近期的几个Mono版本,由于官方所提供的源码包中出现代码文件的缺失,这总让我们的付出变得徒劳.另外一方 ...

  2. 如何安装并简单的使用OwinHost——Katana

    微软OWIN的提出必然会引起一场风暴,而我们作为C#阵营中一份子,自然免不了会卷入其中.OWIN是什么东西,我在这里就不解析了,还不知道是OWIN是什么的读者请打开浏览器,然后搜索即可,中文的英文的应 ...

  3. 高性能的关键:Spring MVC的异步模式

    我承认有些标题党了,不过话说这样其实也没错,关于“异步”处理的文章已经不少,代码例子也能找到很多,但我还是打算发表这篇我写了好长一段时间,却一直没发表的文章,以一个更简单的视角,把异步模式讲清楚. 什 ...

  4. MVVM大比拼之avalon.js源码精析

    简介 avalon是国内 司徒正美 写的MVVM框架,相比同类框架它的特点是: 使用 observe 模式,性能高. 将原始对象用object.defineProperty重写,不需要用户像用knoc ...

  5. ASP.NET MVC Model验证(二)

    ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...

  6. js和jquery实现简单的选项卡

    选项卡切换在做网页的时候经常会用到,以往都是用JQ来实现,代码简单易懂,今天用原生的js实现了一下,二者还是有很大不同的,可以对比一下代码来研究一下. <!DOCTYPE html> &l ...

  7. ASP.NET MVC5+EF6+EasyUI 后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航

    系列目录 本节主要知识点是easyui 的手风琴加树结构做菜单导航 有园友抱怨原来菜单非常难看,但是基于原有树形无限级别的设计,没有办法只能已树形展示 先来看原来的效果 改变后的效果,当然我已经做好了 ...

  8. git常用操作命令

    使用git进行版本控制,分为两部分: 一: 服务端 1.1 首先要申请一个git的账号,方便团队协作.推荐开源中国(www.oschina.net),相对于github来说,有两个优点:1.访问速度很 ...

  9. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇二:基于OneNote难点突破和批量识别

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  10. 学习SpringMVC——说说视图解析器

    各位前排的,后排的,都不要走,咱趁热打铁,就这一股劲我们今天来说说spring mvc的视图解析器(不要抢,都有位子~~~) 相信大家在昨天那篇如何获取请求参数篇中都已经领略到了spring mvc注 ...