分为​​LXCalendarHearder​​,​​LXCalendarWeekView​​以及​​collectionView​​封装的日历控件。

​header​​和​​weekView​​就不用多说了,最重要的是​​collectionView​​的模型建立。有的是把一个月的数据放在一个模型里,想了想还是把每一天的数据单独建立一个模型。

​month​​模型:


​@property (nonatomic, strong) NSDate *monthDate; //!< 传入的 NSDate 对象,该 NSDate 对象代表当前月的某一日,根据它来获得其他数据​

@property (nonatomic, assign) NSInteger totalDays; //!< 当前月的天数
@property (nonatomic, assign) NSInteger firstWeekday; //!< 标示第一天是星期几(0代表周日,1代表周一,以此类推)
@property (nonatomic, assign) NSInteger year; //!< 所属年份
@property (nonatomic, assign) NSInteger month; //!< 当前月份

- (instancetype)initWithDate:(NSDate *)date;


 

​DayModel​​模型:


@interface LXCalendarDayModel : NSObject

@property (nonatomic, assign) NSInteger totalDays; //!< 当前月的天数
@property (nonatomic, assign) NSInteger firstWeekday; //!< 标示第一天是星期几(0代表周日,1代表周一,以此类推)
@property (nonatomic, assign) NSInteger year; //!< 所属年份
@property (nonatomic, assign) NSInteger month; //!< 当前月份
@property (nonatomic, assign) NSInteger day; //每天所在的位置

@property(nonatomic,assign)BOOL isLastMonth;//属于上个月的
@property(nonatomic,assign)BOOL isNextMonth;//属于下个月的
@property(nonatomic,assign)BOOL isCurrentMonth;//属于当月

@property(nonatomic,assign)BOOL isToday;//今天

@property(nonatomic,assign)BOOL isSelected;//是否被选中


根据month模型建立DayModel模型:



 LXCalendarDayModel *model =[[LXCalendarDayModel alloc]init];

//配置外面属性
[self configDayModel:model];

model.firstWeekday = firstWeekday;
model.totalDays = totalDays;

model.month = monthModel.month;

model.year = monthModel.year;


//上个月的日期
if (i < firstWeekday) {
model.day = lastMonthModel.totalDays - (firstWeekday - i) + 1;
model.isLastMonth = YES;
}

//当月的日期
if (i >= firstWeekday && i < (firstWeekday + totalDays)) {

model.day = i -firstWeekday +1;
model.isCurrentMonth = YES;

//标识是今天
if ((monthModel.month == [[NSDate date] dateMonth]) && (monthModel.year == [[NSDate date] dateYear])) {
if (i == [[NSDate date] dateDay] + firstWeekday - 1) {

model.isToday = YES;

}
}

}
//下月的日期
if (i >= (firstWeekday + monthModel.totalDays)) {

model.day = i -firstWeekday - nextMonthModel.totalDays +1;
model.isNextMonth = YES;

}


上面的处理主要是把上个月和下个月需要显示的日期和当月的日期全部塞进​​DayModel​​模型里。这样我们对​​cell​​的处理只需要根据​​DayModel​​即可。

细节说明

​demo​​中只是使用了一个​​collectionView​​然后添加左右清扫手势,给​​collectionView​​的​​layer​​做一个假假的动画实现翻页效果。

关于日历demo中设置了6 行,具体为什么参考日历的12月份。

最后

demo中设置了一些常见的属性,可以自行配置,需要注意的是在属性设置之后才可以处理数据。

使用方法:



self.calenderView =[[LXCalendarView alloc]initWithFrame:CGRectMake(20, 80, Device_Width - 40, 0)];

self.calenderView.currentMonthTitleColor =[UIColor hexStringToColor:@"2c2c2c"];
self.calenderView.lastMonthTitleColor =[UIColor hexStringToColor:@"8a8a8a"];
self.calenderView.nextMonthTitleColor =[UIColor hexStringToColor:@"8a8a8a"];

self.calenderView.isHaveAnimation = NO;

self.calenderView.isCanScroll = YES;
self.calenderView.isShowLastAndNextBtn = NO;

self.calenderView.isShowLastAndNextDate = YES;

self.calenderView.todayTitleColor =[UIColor redColor];

self.calenderView.selectBackColor =[UIColor greenColor];

[self.calenderView dealData];

self.calenderView.backgroundColor =[UIColor whiteColor];
[self.view addSubview:self.calenderView];

self.calenderView.selectBlock = ^(NSInteger year, NSInteger month, NSInteger day) {
NSLog(@"%ld年 - %ld月 - %ld日",year,month,day);
};


代码中选中的日期在滑动会清除选中日期,修复代码如下:



 [self.monthdataA enumerateObjectsUsingBlock:^(LXCalendarDayModel * obj, NSUInteger idx, BOOL * _Nonnull stop) {

if ((obj.year == self.selectModel.year) && (obj.month == self.selectModel.month) && (obj.day == self.selectModel.day)) {
obj.isSelected = YES;
}
}];


如果是自定义日历,动画效果会超出显示区域,此时设置

​self.calenderView.layer.masksToBounds = YES;​​裁剪动画区域即可。

最新代码请移步demo 地址。

 

--------------------

 




最近工作量不大,利用一些时间来实现一此demo,大家可以一起交流与学习。

  • 对于NSCalendar大家或许不陌生,在以前喜欢使用比如FSCalendar第三方日历框架,也是非常好用,功能也非常强大,但大部分功能可能用不上,所以有时间何不自己封装一个呢。

1.日历继承于UIView,内部实现使用UICollectionView。

接口如下:



@class GBCalendar;

@protocol GBCalendarDelegate <NSObject>

- (void)calendar:(GBCalendar *)calendar didSelectDate:(NSDate *)date;

@end

@protocol GBCalendarDataSource <NSObject>

@property (nonatomic, weak) id <GBCalendarDelegate> delegate;


2.如何使用GBCalendar



    GBCalendar *calendar = [[GBCalendar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 700)];
calendar.delegate = self;
[self.view addSubview:calendar];


3.最后附上代码,欢迎大家下载。。。