IOS UICollectionView完成日历的自定义

我们先看看效果图,是使用UICollectionView完成的一个日历的封装。

这里写图片描述

这里写图片描述

大家可以看到,这是使用UICollectionView完成的。日历可以上下滑动月数和年份,今天和过去的时间是可以操作的未来的时间为灰色,不可操作。日历支持选择时间点和时间段,都可以,选择时间段的时候,时间范围内的日期会高亮起来。

实现思路:好吧~日历的编写还是比较麻烦的,大家能借用到三方还是用三方吧。

1.使用分组的UICollectionView,每一个组头显示年份和月份,分组里边是每一天。
2.苹果系统内部自带有很多获取时间数据的方法,包括获取年份啊、月啊或者日,相关的时间数据方法,系统自带需要大家去了解查询。
3.从系统获取时间数据之后,我们会与今天的时间进行一个比较,早于今天的数据可以交互,文本高亮,晚于今天的时间,文本灰色,关闭交互。这在实现UICollectionView的- (UICollectionViewCell )collectionView:(UICollectionView )collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath协议方法的时候会进行一个比较复杂的逻辑判断。
4.实现选择时间范围的时候,我们会为自定义的UICollectionViewCell类编写一个外部可以调用的,刷新改变item颜色和文字的方法:

[cell reloadCellWithFirstDay:self.firstDay andLastDay:self.lastDay andCurrentDay:@[[NSNumber numberWithInteger:[components year]], [NSNumber numberWithInteger:[components month]], [NSNumber numberWithInteger:i - firstWeekDay + 1]]];

也就是上面这个方法,请大家特别注意。它是放在cellForItemAtIndexPath这个协议方法里面调用的,目的就是为了改变用户所选择的时间范围内的UI.它的具体实现在自定义UICollectionViewCell的内部,也是一个比较时间的过程。
5.主要给大家提供一个思路,大家有思路后,可以编写出更好看的日历控件。

好了,上代码

1.自定义UICollectionViewCell
.h

#import <UIKit/UIKit.h>

@interface CanderCollectionViewCell : UICollectionViewCell

@property (nonatomic,strong)UILabel *Label;

@property (nonatomic, strong)NSString *Flag;

//**参数1:开始时间,参数2:结束时间,参数3:当前cell时间;
- (void)reloadCellWithFirstDay:(NSArray *)firstDay andLastDay:(NSArray *)lastDay andCurrentDay:(NSArray *)currentDay;

@end

2.自定义UICollectionViewCell
.m

#import "CanderCollectionViewCell.h"

@implementation CanderCollectionViewCell

- (instancetype)initWithFrame:(CGRect)frame
{

    self = [super initWithFrame:frame];
    if (self) {

        [self.contentView addSubview:self.Label];
    }

    return self;

}

- (UILabel *)Label
{
    if (!_Label) {

        _Label = [[UILabel alloc] initWithFrame:self.bounds];
        [_Label setTextAlignment:NSTextAlignmentCenter];
        [_Label setFont:[UIFont systemFontOfSize:[ZWFlexibieTool floatWithOriginalFloat:15.5 isFlexibleHeight:NO]]];
        _Label.layer.masksToBounds = YES;
        _Label.layer.cornerRadius = [ZWFlexibieTool floatWithOriginalFloat:5 isFlexibleHeight:NO];

    }

    return _Label;
}

- (void)reloadCellWithFirstDay:(NSArray *)firstDay andLastDay:(NSArray *)lastDay andCurrentDay:(NSArray *)currentDay{

        //在空白的情况就让空白不显示
        if (self.Label.text.length == 0) {

           self.hidden = YES;

        }else{

           self.hidden = NO;

        }

        if ([firstDay isEqual:currentDay]) {//第三次点击的时候,改变点击的那个Cell颜色

            self.Label.backgroundColor = COLOR_RGB(73, 105, 248);
            self.Label.textColor = [UIColor whiteColor];

        }else if (firstDay.count != 0 && lastDay.count != 0){//此处判断的是处于中间的

            //三个日期
            NSDate *FirstDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",firstDay[0],firstDay[1],firstDay[2]] withDateFormat:@"yyyy-MM-dd"];

            NSDate *LastDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",lastDay[0],lastDay[1],lastDay[2]] withDateFormat:@"yyyy-MM-dd"];

            NSDate *currentDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",currentDay[0],currentDay[1],currentDay[2]] withDateFormat:@"yyyy-MM-dd"];

            if ((currentDate > FirstDate && currentDate < LastDate) || (currentDate  < FirstDate && currentDate > LastDate)) {

                self.Label.backgroundColor = COLOR_RGB(127, 144, 219);
                self.Label.textColor = [UIColor whiteColor];
            }

            if (currentDate == FirstDate || currentDate == LastDate) {

                self.Label.backgroundColor = COLOR_RGB(73, 105, 248);
                self.Label.textColor = [UIColor whiteColor];

            }

        }

}

3.自定义UICollectionView 的头部视图
.h

#import <UIKit/UIKit.h>

@interface CanderCollectionReusableView : UICollectionReusableView

@property (nonatomic, strong) UILabel *YerMonLabel;//年月展示标签

@property (nonatomic, strong) UIView  *BehindView;
@end

4.自定义UICollectionView 的头部视图
.m

#import "CanderCollectionReusableView.h"

@implementation CanderCollectionReusableView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self) {

        //加载视图
        [self addSubview:self.BehindView];
        [self.BehindView addSubview:self.YerMonLabel];

    }

    return self;
}

#pragma mark -  Getter methods

- (UILabel *)YerMonLabel {

    if (!_YerMonLabel) {

        _YerMonLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, CGRectGetWidth(self.bounds), 30)];
        _YerMonLabel.textAlignment = 0;

        _YerMonLabel.textColor = [UIColor grayColor];
        _YerMonLabel.backgroundColor = [UIColor whiteColor];
        _YerMonLabel.font = [UIFont boldSystemFontOfSize:12];
    }

    return _YerMonLabel;

}

- (UIView *)BehindView{

    if (!_BehindView) {
        _BehindView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 30)];
        _BehindView.backgroundColor = [UIColor whiteColor];
    }
    return _BehindView;
}
@end

5.说明一下,日历我是封装在控制器当中的,具有一些回调协议用于传值,选择的时间范围不能超过一年,这是我具体工作中的要求,大家有思路后可以进行修改。

日历控制器.h

#import <UIKit/UIKit.h>

@protocol CanderViewControllerDelegate <NSObject>

@optional
//回传值到首页的协议
- (void)CanderViewControllerGiveWith:(NSString *)StartTime WithEndTime:(NSString *)EndTime;

@end

@interface CanderViewController : UIViewController

//设置代理
@property (nonatomic, weak) id <CanderViewControllerDelegate> delegate;

@property (nonatomic, strong) NSDateFormatter * formatter; //时间书写格式

@property (nonatomic, strong) NSDateComponents * components; //当前日期的零件

@property (nonatomic, strong) NSCalendar * calendar; //当前日历

@property (nonatomic, strong) NSArray * firstDay;//出发时间

@property (nonatomic, strong) NSArray * lastDay;//返回时间

//属性传值
@property (nonatomic, strong) NSString *StartValue;//接收主页回传时间值

@property (nonatomic, strong) NSString *EndValue;//接收主页回传时间值

@property (nonatomic, copy)   NSString *EarningStr;

@end

日历控制器.m 这里有上千行代码,真的是太烦了~

#import "CanderViewController.h"

#import "CanderCollectionViewCell.h"

#import "CanderCollectionReusableView.h"//头部视图

@interface CanderViewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UIGestureRecognizerDelegate>{

    NSIndexPath *TodayIndexPath;//今日的表格路径

    BOOL    isFirst;

}

@property (nonatomic,strong)UICollectionView *CandercollectionView;

@property (nonatomic,strong)UICollectionViewFlowLayout *CanderflowLayout;

@property (nonatomic , strong) NSDate *date;//时间

@property (nonatomic , strong) NSDate *today;//今天的时间

@property (nonatomic, strong)UIButton *SureButton;//确定按钮

@property (nonatomic, strong)UILabel *StartLabel;//开始时间

@property (nonatomic, strong)UILabel *EndLabel;//结束时间

@property (nonatomic, strong)UIImageView *FlyImageView;//飞行图标

@property (nonatomic, strong)UITapGestureRecognizer *TapGester;//点击手势

@end

@implementation CanderViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    self.title = @"日期选择";
//    self.tabBarController.tabBar.hidden = YES;//隐藏标签控制器
    self.view.backgroundColor = [UIColor whiteColor];
    self.date = [NSDate date];
    self.today = self.date;//注意这里的时间给值方式,必须这么给值,不然后面的时间判断会出错。
    [self.view addSubview:self.SureButton];
    [self.view addSubview:self.CandercollectionView];

    [self.view addSubview:self.EndLabel];
    [self.view addSubview:self.StartLabel];
    [self.view addSubview:self.FlyImageView];


    [_SureButton mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.mas_equalTo(self.view.mas_left).offset(10);
        make.right.mas_equalTo(self.view.mas_right).offset(-10);
        make.bottom.mas_equalTo(self.view.mas_bottom).offset(-10);
        make.height.mas_equalTo(45);

    }];

    [_CandercollectionView mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.mas_equalTo(self.view.mas_left).offset(0);
        make.right.mas_equalTo(self.view.mas_right).offset(0);
        make.bottom.mas_equalTo(_SureButton.mas_top).offset(-10);
        make.top.mas_equalTo(_StartLabel.mas_bottom).offset(40);

    }];

    [_EndLabel mas_makeConstraints:^(MASConstraintMaker *make) {


        make.right.mas_equalTo(self.view.mas_right).offset(-10);
        make.top.mas_equalTo(self.view.mas_top).offset(15);
        make.height.mas_equalTo(30);
        make.width.mas_equalTo(130);
    }];

    [_StartLabel mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.mas_equalTo(self.view.mas_left).offset(10);
        make.top.mas_equalTo(self.view.mas_top).offset(15);
        make.height.mas_equalTo(30);
        make.width.mas_equalTo(130);


    }];

    [_FlyImageView mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.mas_equalTo(_StartLabel.mas_right).offset(40);
        make.top.mas_equalTo(self.view.mas_top).offset(20);
        make.height.width.mas_equalTo(20);

    }];

    [self WeeksDayMethods];


}

- (void)WeeksDayMethods{

    NSArray *WeekArr = @[@"SUN",@"MON",@"TUE",@"WED",@"THU",@"FRI",@"SAT"];

    for (int i = 0; i < 7; i++) {

        UILabel *label = [[UILabel alloc]init];
        label.backgroundColor = [UIColor whiteColor];
        label.textColor = COLOR_RGB(73, 105, 248);
        label.textAlignment = 1;
        label.text = [WeekArr objectAtIndex:i];
        label.font = [UIFont boldSystemFontOfSize:[ZWFlexibieTool floatWithOriginalFloat:11 isFlexibleHeight:NO]];
        [self.view addSubview:label];

        [label mas_makeConstraints:^(MASConstraintMaker *make) {

            make.top.mas_equalTo(_StartLabel.mas_bottom).offset(15);
            make.width.mas_equalTo(SCREEN_W/7);
            make.height.mas_equalTo(25);
            make.left.mas_equalTo(self.view.mas_left).offset(0+i*SCREEN_W/7);

        }];

    }

}

-(void)setDate:(NSDate *)date{

    _date = date;

}

#pragma mark - 时间的方法.刘虎(下)----------------------------------------------------------

//得到今天是几号
- (NSInteger)day:(NSDate *)date{

    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];

    //    NSLog(@"得到现在的这个时间是多少日%ld",(long)[components day]);

    return [components day];

}
//得到今天是几月
- (NSInteger)month:(NSDate *)date{

    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];

    //    NSLog(@"得到现在的这个时间是多少月%ld",(long)[components month]);

    return [components month];

}

//得到今年是几年
- (NSInteger)year:(NSDate *)date{

    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];

    //    NSLog(@"得到现在的这个时间是多少年%ld",(long)[components year]);
    return [components year];

}

//计算每个月的第一天在星期几,从哪一个单元格开始。
- (NSInteger)firstWeekdayInThisMonth:(NSDate *)date{

    NSCalendar *calendar = [NSCalendar currentCalendar];

    [calendar setFirstWeekday:1];//1.Sun. 2.Mon. 3.Thes. 4.Wed. 5.Thur. 6.Fri. 7.Sat.
    NSDateComponents *comp = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];
    [comp setDay:1];
    NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];

    NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate];

    return firstWeekday-1;

}

//这个月有多少天
- (NSInteger)totaldaysInThisMonth:(NSDate *)date{
    NSRange totaldaysInMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];

    //    NSLog(@"这个月有几天%lu",(unsigned long)totaldaysInMonth.length);//看这个月有多少天

    return totaldaysInMonth.length;

}

//上个月的date数据(用于刷新)
- (NSDate *)lastMonth:(NSDate *)date{

    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    dateComponents.month = -1;//递归减一,上个月的数据

    NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:date options:0];

    //    NSLog(@"上个月的date数据 = %@",newDate);//比如现在是2016年7月1日,这里输出的是2016年6月1日

    return newDate;

}

//下个月的date数据(用于刷新)
- (NSDate*)nextMonth:(NSDate *)date{

    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    dateComponents.month = +1;//递归加一,下个月的数据
    NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:date options:0];

    //    NSLog(@"下个月的date数据 = %@",newDate);//比如现在是2016年7月1日,这里输出的是2016年8月1日

    return newDate;
}

#pragma mark -------------------------时间的方法.刘虎(上)------------------------------------------------
#pragma mark -刘虎方法在于分别展示每个月的日历,网上方法在于很多年日历一起铺开。

#pragma mark - 集合视图协议方法

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{

    return 60;

}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

    if ([self ReturnDaysNumeber:section] > 35) {

        return 42;

    }else{

        return 35;

    }

}

- (NSInteger)ReturnDaysNumeber:(NSInteger)Section{

    //此方法就是在计算每个月的时间,为每个月数据的铺开创造条件
    NSDate * dateTime = [self getEarlierAndLaterDaysFromDate:self.today withMonth:Section];

    NSInteger daysInThisMonth = [self totaldaysInThisMonth:dateTime];//这个月有多少天
    NSInteger firstWeekDay = [self firstWeekdayInThisMonth:dateTime];//计算每个月的第一天在星期几,从哪一个单元格开始。(可以确定从哪一行开始)

    return daysInThisMonth+firstWeekDay;

}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

    NSDate * dateTime = [self getEarlierAndLaterDaysFromDate:self.today withMonth:indexPath.section];

    NSInteger dayIndex = indexPath.row - [self getBeginTimeInMonth:dateTime].integerValue + 1;

    NSDateComponents *components = [self getCurrentComponentWithDate:dateTime];

    NSInteger firstWeekDay = [self firstWeekdayInThisMonth:dateTime];//计算每个月的第一天在星期几,从哪一个单元格开始。(可以确定从哪一行开始)

    //由于当前日期的cell处于选中状态,我们找到它,将它颜色变回来.这里需要判断路径是不是相同
    if (![TodayIndexPath isEqual:indexPath]) {

        CanderCollectionViewCell *Todaycell = (CanderCollectionViewCell *)[collectionView cellForItemAtIndexPath:TodayIndexPath];
        Todaycell.Label.textColor = [UIColor blackColor];
        Todaycell.Label.backgroundColor = [UIColor whiteColor];
        Todaycell.Flag = @"0";

    }

    //数组有数据说明是上次预留,清空数据。
    if (self.lastDay.count != 0 && self.firstDay.count != 0) {

        self.firstDay = nil;
        self.lastDay = nil;

    }

    //把开始和结束的时间给值
    if (self.firstDay.count == 0) {

        //第一次点击给值
        self.firstDay = @[[NSNumber numberWithInteger:[components year]],[NSNumber numberWithInteger:[components month]],[NSNumber numberWithInteger:dayIndex-firstWeekDay]];

//        NSLog(@"开始时间==%@",self.firstDay);

        [self.SureButton setTitle:@"已选(0)天" forState:UIControlStateNormal];

        [self.CandercollectionView reloadData];

    }else {

        //第二次点击给值
        self.lastDay = @[[NSNumber numberWithInteger:[components year]],[NSNumber numberWithInteger:[components month]],[NSNumber numberWithInteger:dayIndex-firstWeekDay]];

        [self CompareDateAndGiveValue:[NSString stringWithFormat:@"%@-%@-%@",self.firstDay[0],self.firstDay[1],self.firstDay[2]] With:[NSString stringWithFormat:@"%@-%@-%@",self.lastDay[0],self.lastDay[1],self.lastDay[2]]];

        [self.CandercollectionView reloadData];

        NSDate *FirstDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",self.firstDay[0],self.firstDay[1],self.firstDay[2]] withDateFormat:@"yyyy-MM-dd"];

        NSDate *LastDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",self.lastDay[0],self.lastDay[1],self.lastDay[2]] withDateFormat:@"yyyy-MM-dd"];

        //计算两个中间差值(秒)
        NSTimeInterval time = [LastDate timeIntervalSinceDate:FirstDate];

        //开始时间和结束时间的中间相差的时间
        int days;
        days = ((int)time)/(3600*24)+1;  //一天是24小时*3600秒

        if (days < 0) {

            days = days *-1;

        }

        NSString * dateValue = [NSString stringWithFormat:@"%i",days];

        [self.SureButton setTitle:[NSString stringWithFormat:@"已选(%@)天",dateValue] forState:UIControlStateNormal];

    }

    //这里找到的是那个被选中的cell
    CanderCollectionViewCell *cell = (CanderCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
    cell.Label.backgroundColor = [UIColor blueColor];
    cell.Label.textColor = [UIColor whiteColor];
    cell.Flag = @"1";

}

- (void)CompareDateAndGiveValue:(NSString *)StartStr With:(NSString *)EndStr{

    NSDate *DateOne = [ZWTool stringToDate:StartStr withDateFormat:@"yyyy-MM-dd"];

    NSDate *DateTwo = [ZWTool stringToDate:EndStr withDateFormat:@"yyyy-MM-dd"];

    if ([DateOne compare:DateTwo] == NSOrderedAscending) {//左边的小于右边的

        self.StartLabel.text = StartStr;
        self.EndLabel.text = EndStr;

    }else if ([DateOne compare:DateTwo] == NSOrderedSame){//这里是两次的时间都一样

        self.StartLabel.text = StartStr;
        self.EndLabel.text = EndStr;

    }
    else{

        self.StartLabel.text = EndStr;
        self.EndLabel.text = StartStr;

    }

}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{

    CanderCollectionViewCell *cell = (CanderCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];

    cell.Label.backgroundColor = [UIColor whiteColor];
    cell.Label.textColor = [UIColor blackColor];
    cell.Flag = @"0";

}

//头部视图
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {

    //重用
    CanderCollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CanderHeader" forIndexPath:indexPath];

    NSArray *HeadDateArr = (NSArray *)[self getTimeFormatArrayWithDate:self.today andMonth:indexPath.section];

    headerView.YerMonLabel.text = [NSString stringWithFormat:@"%@年%@月",HeadDateArr[0],HeadDateArr[1]];

    return headerView;

}

#pragma mark -------------------------网上方法(下)------------------------------------------------

/**获取每个单位内开始时间*/
- (NSString *)getBeginTimeInMonth:(NSDate *)date {

    NSTimeInterval count = 0;
    NSDate * beginDate = nil;
    NSCalendar * calendar = [NSCalendar currentCalendar];

    //返回日历每个月份的开始时间,类型是unitMonth
    BOOL findFirstTime = [calendar rangeOfUnit:NSCalendarUnitMonth startDate:&beginDate interval:&count forDate:date];

    if (findFirstTime) {

        return nil;
    }else {
        return @"";
    }

}

/**获取当前日期格式*/
- (NSArray *)getTimeFormatArrayWithDate:(NSDate *)date andMonth:(NSInteger)month {

    NSDate * dateTime = [self getEarlierAndLaterDaysFromDate:self.today withMonth:month];
    NSString * stringFormat = [self.formatter stringFromDate:dateTime];
    //通过“-”拆分日期格式
    return [stringFormat componentsSeparatedByString:@"-"];
}

//**根据当前时间获取当前和以后各有多少个月,0为当前月*/
- (NSDate *)getEarlierAndLaterDaysFromDate:(NSDate *)date withMonth:(NSInteger)month {

    NSDate * newDate = [NSDate date];

    NSDateComponents * components = [self getCurrentComponentWithDate:newDate];

    //获取section表示的每个月份
    NSInteger year = [components year];
    NSInteger month_n = [components month];

    //希望从哪年开始写日历 例如2016年

    NSInteger month_count = (year - 2015) * 12;

    //获取当前section代表的月份和现在月份的差值
    NSInteger months = month - month_count - month_n + 1;

    [self.components setMonth:months];

    //返回各月份的当前日期,如:2016-01-14,2016-02-14
    NSDate * ndate = [self.calendar dateByAddingComponents:self.components toDate:date options:0];

    return ndate;

}

/**获取当前日期零件*/
- (NSDateComponents *)getCurrentComponentWithDate:(NSDate *)dateTime {
    NSCalendar * calendar = [NSCalendar currentCalendar];
    //日期拆分类型
    NSCalendarUnit unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitDay;
    return [calendar components:unitFlags fromDate:dateTime];
}

- (NSDateFormatter *)formatter {

    if (!_formatter) {
        _formatter = [[NSDateFormatter alloc] init];
        _formatter.dateFormat = @"yyyy-MM-dd";
    }
    return _formatter;
}

- (NSDateComponents *)components {
    if (!_components) {
        _components = [[NSDateComponents alloc] init];
    }
    return _components;
}

- (NSCalendar *)calendar {
    if (!_calendar) {
        _calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    }
    return _calendar;
}

//这里的功能是让日历定位到今天所在的那个月。
- (void)viewDidLayoutSubviews{

    if (isFirst == NO) {

        NSDate *now = [NSDate date];
        NSCalendar *calendar = [NSCalendar currentCalendar];
        NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
        NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:now];
        NSInteger year = [dateComponent year];
        NSInteger month1 = [dateComponent month];
        NSInteger day = [dateComponent day];
        //NSInteger hour = [dateComponent hour];
        //NSInteger minute = [dateComponent minute];
        //NSInteger second = [dateComponent second];

        //这里写的2015,就是2015年一月一日开始
        NSInteger months = (year - 2015) * 12 + month1 - 1;

        [self.CandercollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:day inSection:months] atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];

        isFirst = YES;

    }else{

        return;
    }

}


#pragma mark --------------------------网上方法(上)----------------------------------------------
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    CanderCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

    cell.Flag = @"0";

    //此方法就是在计算每个月的时间,为每个月数据的铺开创造条件
    NSDate * dateTime = [self getEarlierAndLaterDaysFromDate:self.today withMonth:indexPath.section];

    NSInteger daysInThisMonth = [self totaldaysInThisMonth:dateTime];//这个月有多少天
    NSInteger firstWeekDay = [self firstWeekdayInThisMonth:dateTime];//计算每个月的第一天在星期几,从哪一个单元格开始。(可以确定从哪一行开始)
    NSInteger day = 0;
    NSInteger i = indexPath.row;

    //小于第一天所在的行数
    if (i < firstWeekDay) {

        cell.Label.text = @"";//集合视图,i为重用的时候,当前的item数,当i小于第一天所在的行数的时候,文本为空。
        cell.Label.backgroundColor = [UIColor whiteColor];

        //大于第一天所在的行数
    }else if (i > firstWeekDay + daysInThisMonth - 1){

        cell.Label.text = @"";//同理集合视图,i为重用的时候,当前的item数,当i大于第一天所在的行数的时候,文本为空。
        cell.Label.backgroundColor = [UIColor whiteColor];

    }else{

        //中间的
        day = i - firstWeekDay + 1;//计算每个item需要显示的数字文本
        cell.Label.text = [NSString stringWithFormat:@"%ld",(long)day];//给每个item文本给值

        //cell重用的时候的颜色设置
        if ([cell.Flag isEqualToString:@"1"]) {

            cell.Label.backgroundColor = COLOR_RGB(73, 105, 248);
            cell.Label.textColor = [UIColor whiteColor];

        }else{

            cell.Label.backgroundColor = [UIColor whiteColor];
            cell.Label.textColor = [UIColor blackColor];

        }

        if ([_today isEqualToDate:dateTime]) {//这是在处理本日所在的月份的这一组集合视图的样式。

            if (day == [self day:dateTime]) {//[self day:_date]是得到今天是几号的方法,如果今天的日期刚好等于day,那么文本为红色
                cell.Label.text = @"今天";
                cell.Label.textColor = [UIColor whiteColor];
                cell.Label.backgroundColor = COLOR_RGB(231, 88, 84);

                //记录当前的日期的Cell的NSIndexPath
                TodayIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
                //让当前日期的cell处于选中状态
                //                    cell.Flag = @"1";

            }else if (day > [self day:dateTime]){//如果是大于的话就是暗灰色。

                cell.Label.textColor = [UIColor lightGrayColor];

            }

        }else if ([_today compare:dateTime] == NSOrderedAscending){//这是在处理未来时间,也就是未来的时间月份的样式

            //NSOrderedAscending的意思是:左边的操作对象小于右边的对象。
            //NSOrderedDescending的意思是:左边的操作对象大于右边的对象。
            cell.Label.backgroundColor = [UIColor whiteColor];
            cell.Label.textColor = [UIColor lightGrayColor];//此代码指的是未来的时间的文本颜色。
            cell.userInteractionEnabled = NO;//未来时间不允许选取

        }

    }

    if (cell.Label.text.length == 0 || [cell.Label.textColor isEqual:[UIColor lightGrayColor]]) {

        cell.userInteractionEnabled = NO;

    }else{

        cell.userInteractionEnabled = YES;

    }

    //刷新UI控件
    NSDateComponents * components = [self getCurrentComponentWithDate:dateTime];
    [cell reloadCellWithFirstDay:self.firstDay andLastDay:self.lastDay andCurrentDay:@[[NSNumber numberWithInteger:[components year]], [NSNumber numberWithInteger:[components month]], [NSNumber numberWithInteger:i - firstWeekDay + 1]]];

    return cell;

}

- (UICollectionViewFlowLayout *)CanderflowLayout{

    if (!_CanderflowLayout) {

        _CanderflowLayout = [[UICollectionViewFlowLayout alloc]init];
        _CanderflowLayout.minimumInteritemSpacing = [ZWFlexibieTool floatWithOriginalFloat:2 isFlexibleHeight:NO];
        _CanderflowLayout.minimumLineSpacing = [ZWFlexibieTool floatWithOriginalFloat:5 isFlexibleHeight:NO];
        _CanderflowLayout.itemSize = CGSizeMake([ZWFlexibieTool floatWithOriginalFloat:50 isFlexibleHeight:NO], [ZWFlexibieTool floatWithOriginalFloat:50 isFlexibleHeight:NO]);
        _CanderflowLayout.sectionInset = UIEdgeInsetsMake([ZWFlexibieTool floatWithOriginalFloat:5 isFlexibleHeight:NO], [ZWFlexibieTool floatWithOriginalFloat:5 isFlexibleHeight:NO], [ZWFlexibieTool floatWithOriginalFloat:5 isFlexibleHeight:NO], [ZWFlexibieTool floatWithOriginalFloat:5 isFlexibleHeight:NO]);
        //设置头部视图的高度
        _CanderflowLayout.headerReferenceSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 44);
        _CanderflowLayout.sectionHeadersPinToVisibleBounds = NO;

    }
    return _CanderflowLayout;
}

- (UICollectionView *)CandercollectionView{

    if (!_CandercollectionView) {

        _CandercollectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:self.CanderflowLayout];
        [_CandercollectionView registerClass:[CanderCollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
        _CandercollectionView.delegate = self;
        _CandercollectionView.dataSource = self;
        _CandercollectionView.bounces = NO;
        _CandercollectionView.backgroundColor = [UIColor whiteColor];
        [_CandercollectionView registerClass:[CanderCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CanderHeader"];

    }
    return _CandercollectionView;
}

- (UIButton *)SureButton{

    if (!_SureButton) {

        _SureButton  = [[UIButton alloc]init];
        _SureButton.backgroundColor = COLOR_RGB(73, 105, 248);
        [_SureButton setTitle:@"已选(0)天" forState:UIControlStateNormal];
        [_SureButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [_SureButton addTarget:self action:@selector(respondsToSureButton:) forControlEvents:UIControlEventTouchUpInside];
        _SureButton.layer.masksToBounds = YES;
        _SureButton.layer.cornerRadius = 3;

    }
    return _SureButton;
}

//开始时间
- (UILabel *)StartLabel{

    if (!_StartLabel) {

        _StartLabel = [[UILabel alloc]init];
        _StartLabel.backgroundColor = COLOR_RGB(73, 105, 248);
        _StartLabel.textAlignment = 1;
        _StartLabel.tag = 1;

        if (self.StartValue.length > 0) {

            _StartLabel.text = self.StartValue;

        }else{

            _StartLabel.text = [self getStartTimeStr];

        }
        _StartLabel.textColor = [UIColor whiteColor];
        _StartLabel.layer.masksToBounds = YES;
        _StartLabel.layer.cornerRadius = 3;
        _StartLabel.font = [UIFont systemFontOfSize:[ZWFlexibieTool floatWithOriginalFloat:12 isFlexibleHeight:NO]];
        _StartLabel.userInteractionEnabled = YES;
        //添加手势
        [_StartLabel addGestureRecognizer:self.TapGester];

    }
    return _StartLabel;
}

//结束时间
- (UILabel *)EndLabel{

    if (!_EndLabel) {

        _EndLabel = [[UILabel alloc]init];
        _EndLabel.backgroundColor = COLOR_RGB(73, 105, 248);
        _EndLabel.textAlignment = 1;
        _EndLabel.tag = 2;

        if (self.EndValue.length > 0) {

            _EndLabel.text = self.EndValue;

        }else{

            _EndLabel.text = [self getEndTimeStr];
        }

        _EndLabel.textColor = [UIColor whiteColor];
        _EndLabel.layer.masksToBounds = YES;
        _EndLabel.layer.cornerRadius = 3;
        _EndLabel.font = [UIFont systemFontOfSize:[ZWFlexibieTool floatWithOriginalFloat:12 isFlexibleHeight:NO]];
        _EndLabel.userInteractionEnabled = YES;

        UITapGestureRecognizer *Gester = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToTapGestureRecognizer:)];
        // 设置点击次数
        Gester.numberOfTapsRequired = 1;
        // 设置手指数量
        Gester.numberOfTouchesRequired = 1;

        Gester.delegate = self;


        [_EndLabel addGestureRecognizer:Gester];

    }
    return _EndLabel;
}

- (UITapGestureRecognizer *)TapGester{

    if (!_TapGester) {

        _TapGester = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToTapGestureRecognizer:)];
        // 设置点击次数
        _TapGester.numberOfTapsRequired = 1;
        // 设置手指数量
        _TapGester.numberOfTouchesRequired = 1;

        _TapGester.delegate = self;

    }

    return _TapGester;
}

//点击手势事件
- (void)respondsToTapGestureRecognizer:(UITapGestureRecognizer *)gesture {


    UIDatePicker *picker = [[UIDatePicker alloc]init];
    picker.datePickerMode = UIDatePickerModeDate;
    NSLocale *locale = [[NSLocale alloc]initWithLocaleIdentifier:@"zh_CN"];//设置为中文显示
    picker.locale = locale;//可以设置本地手机的现实模式
    [picker setDate:[NSDate date] animated:YES];//设置当前显示日期

    picker.frame = CGRectMake(0, 30, 350, 200);
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"日期选择\n\n\n\n\n\n\n\n\n\n" message:nil preferredStyle:UIAlertControllerStyleActionSheet];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

        NSDate *senddate=picker.date;
        NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init];
        [dateformatter setDateFormat:@"YYYY-MM-dd"];
        NSString *ChooseString=[dateformatter stringFromDate:senddate];

        if (gesture.view.tag == 1) {//开始文本

            //判断选择的时间是否合法
            NSDate *DateOne = [ZWTool stringToDate:ChooseString withDateFormat:@"yyyy-MM-dd"];

            NSDate *DateTwo = [ZWTool stringToDate:self.EndLabel.text withDateFormat:@"yyyy-MM-dd"];

            if ([DateOne compare:DateTwo] == NSOrderedAscending) {//左边的小于右边的

                self.StartLabel.text = ChooseString;

                //计算两个中间差值(秒)
                NSTimeInterval time = [DateOne timeIntervalSinceDate:DateTwo];

                //开始时间和结束时间的中间相差的时间
                int days;
                days = ((int)time)/(3600*24)+1;  //一天是24小时*3600秒

                if (days < 0) {

                    days = days *-1;

                }

                NSString * dateValue = [NSString stringWithFormat:@"%i",days];

                [self.SureButton setTitle:[NSString stringWithFormat:@"已选(%@)天",dateValue] forState:UIControlStateNormal];

            }else if ([DateOne compare:DateTwo] == NSOrderedSame){//这里是两次的时间都一样

                self.StartLabel.text = ChooseString;
                [self.SureButton setTitle:@"已选(1)天" forState:UIControlStateNormal];
            }
            else{

                UIAlertController *alretController = [UIAlertController alertControllerWithTitle:@"数聚空港" message:@"结束时间不能早于开始时间" preferredStyle:UIAlertControllerStyleAlert];

                [self presentViewController:alretController animated:YES completion:^{

                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                        [self dismissViewControllerAnimated:YES completion:nil];

                    });

                }];

            }





        }else{//结束文本

            //判断选择的时间是否合法
            NSDate *DateOne = [ZWTool stringToDate:self.StartLabel.text withDateFormat:@"yyyy-MM-dd"];

            NSDate *DateTwo = [ZWTool stringToDate:ChooseString withDateFormat:@"yyyy-MM-dd"];

            if ([DateOne compare:DateTwo] == NSOrderedAscending) {//左边的小于右边的

                self.EndLabel.text = ChooseString;

                //计算两个中间差值(秒)
                NSTimeInterval time = [DateOne timeIntervalSinceDate:DateTwo];

                //开始时间和结束时间的中间相差的时间
                int days;
                days = ((int)time)/(3600*24)+1;  //一天是24小时*3600秒

                if (days < 0) {

                    days = days *-1;

                }

                NSString * dateValue = [NSString stringWithFormat:@"%i",days];

                [self.SureButton setTitle:[NSString stringWithFormat:@"已选(%@)天",dateValue] forState:UIControlStateNormal];

            }else if ([DateOne compare:DateTwo] == NSOrderedSame){//这里是两次的时间都一样

                self.EndLabel.text = ChooseString;
                [self.SureButton setTitle:@"已选(1)天" forState:UIControlStateNormal];
            }
            else{

                UIAlertController *alretController = [UIAlertController alertControllerWithTitle:@"数聚空港" message:@"结束时间不能早于开始时间" preferredStyle:UIAlertControllerStyleAlert];

                [self presentViewController:alretController animated:YES completion:^{

                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                        [self dismissViewControllerAnimated:YES completion:nil];

                    });

                }];

            }








        }

    }];

    [alertController.view addSubview:picker];
    [alertController addAction:cancelAction];

    dispatch_async(dispatch_get_main_queue(), ^{

        [self presentViewController:alertController animated:YES completion:nil];
    });


}

- (UIImageView *)FlyImageView{

    if (!_FlyImageView) {

        _FlyImageView = [[UIImageView alloc]init];
        _FlyImageView.image = [UIImage imageNamed:@"日历_image_disabled.png"];

    }

    return _FlyImageView;
}

//得到结束时间
- (NSString *)getEndTimeStr{

    //昨天的时间
    NSDate    *Enddate=[NSDate date];
    NSTimeInterval time = 24 * 60 * 60;//一天的秒数
    NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init];
    NSDate *lastDay = [Enddate dateByAddingTimeInterval:-time];
    [dateformatter setDateFormat:@"YYYY-MM-dd"];

    return [dateformatter stringFromDate:lastDay];

}

//得到开始的时间(倒数60天)
- (NSString *)getStartTimeStr{

    //获取系统时间
    NSDate    *Enddate=[NSDate date];
    NSTimeInterval time = 24 * 60 * 60;//一天的秒数
    NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init];
    NSDate *lastDay = [Enddate dateByAddingTimeInterval:-time*60];
    [dateformatter setDateFormat:@"YYYY-MM-dd"];

    return [dateformatter stringFromDate:lastDay];

}

//确定按钮事件
- (void)respondsToSureButton:(UIButton *)sender{

    if (self.StartLabel.text.length > 0 && self.EndLabel.text.length > 0 && ![self.EndLabel.text isEqualToString:@"请选择结束时间"]) {

        NSDate *FirstDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",self.firstDay[0],self.firstDay[1],self.firstDay[2]] withDateFormat:@"yyyy-MM-dd"];

        NSDate *LastDate = [ZWTool stringToDate:[NSString stringWithFormat:@"%@-%@-%@",self.lastDay[0],self.lastDay[1],self.lastDay[2]] withDateFormat:@"yyyy-MM-dd"];

        //计算两个中间差值(秒)
        NSTimeInterval time = [LastDate timeIntervalSinceDate:FirstDate];

        //开始时间和结束时间的中间相差的时间
        int days;
        days = ((int)time)/(3600*24)+1;  //一天是24小时*3600秒

        if (days < 0) {

            days = days *-1;

        }
        if (days > 366) {

            UIAlertController *alretController = [UIAlertController alertControllerWithTitle:@"数聚空港" message:@"时间跨度选择不能超过一年,请重新选择" preferredStyle:UIAlertControllerStyleAlert];

            UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

                //数组有数据说明是上次预留,清空数据。
                if (self.lastDay.count != 0 && self.firstDay.count != 0) {

                    self.firstDay = nil;
                    self.lastDay = nil;

                }

                [self.CandercollectionView reloadData];

                [self.SureButton setTitle:@"已选(0)天" forState:UIControlStateNormal];
            }];

            [alretController addAction:sureAction];
            [self presentViewController:alretController animated:YES completion:nil];
        }else{


            //将时间值传递到首页,如果客户选择时间值发生变化,首页会将值再次传递到日历控件。
            if (_delegate && [_delegate respondsToSelector:@selector(CanderViewControllerGiveWith:WithEndTime:)]) {

                [_delegate CanderViewControllerGiveWith:self.StartLabel.text WithEndTime:self.EndLabel.text];

            }

            NSDictionary *userInfo = @{@"StartDate":self.StartLabel.text, @"EndDate":self.EndLabel.text};

            if ([self.EarningStr isEqualToString:@"收益"]) {

                [[NSNotificationCenter defaultCenter] postNotificationName:@"CanderEarningDateNotification" object:nil userInfo:userInfo];

                [self.navigationController popViewControllerAnimated:YES];

            }else if ([self.EarningStr isEqualToString:@"航班详情"]){

                [[NSNotificationCenter defaultCenter] postNotificationName:@"FlightDetailNotification" object:nil userInfo:userInfo];

                [self.navigationController popViewControllerAnimated:YES];

            }
            else{

                if ([self.EarningStr isEqualToString:@"准点率"]) {

                    [[NSNotificationCenter defaultCenter] postNotificationName:@"CanderZhunDianLvNotification" object:nil userInfo:userInfo];

                    [self.navigationController popViewControllerAnimated:YES];

                }else{

                    //发送通知传递时间给四个页面,让四个子页面数据刷新。
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"CanderDateNotification" object:nil userInfo:userInfo];

                    [self.navigationController popViewControllerAnimated:YES];

                }



            }


        }

    }else{

        UIAlertController *alretController = [UIAlertController alertControllerWithTitle:@"数聚空港" message:@"开始或结束时间不能为空" preferredStyle:UIAlertControllerStyleAlert];

        [self presentViewController:alretController animated:YES completion:^{

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                [self dismissViewControllerAnimated:YES completion:nil];

            });
        }];

    }

}

@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值