最近接到一个项目,需要一个日历的样式,所以从网上找了一个框架JTCalendar,并成功改成了项目需要的样式,在这里分享使用方法
1.集成框架
可以直接去Github下载 下载地址
将JTCalendar文件夹整个拖进项目里即可
2.日历的组成
1.日历是由两部分组成的,一个显示月份的MenuView,一个显示天数的ContentView.
所以我们需要创建两个View
上面的菜单View是我自定义的一个MenuView,并没有使用框架内自带的,因为框架内自带MenuView的没有左右点击切换月份,但是自带的MenuView是一个ScrollView,可以左右滚动进行月份切换,大家可以根据自己需求进行设置
3.代码实现日历的显示
首选需要导入JTCalendar.h文件
框架内有一个管理者,类似于AFN的Manager,我们需要通过这个Manager来进行ContentView的设置
//创建一个管理者,并且通过属性强引用,使其不会被释放
@property (strong, nonatomic) JTCalendarManager *calendarManager;
//通过New语法来创建管理者
self.calendarManager = [JTCalendarManager new];
//设置需要显示月份的View,我这里是自定义的,所以注释掉了
//[self.calendarManager setMenuView:self.CalendarMenuView];
//设置需要显示日历的View
[self.calendarManager setContentView:self.calendarContentView];
注意需要显示日历的View,必须是JT框架内部的View,不同样式的日历View,需要绑定或创建JT内对应的View。需要什么样式的可以在框架内有案例显示。
我这里创建是可以选中的View所以创建了JTHorizontalCalendarView
@property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;
4.设置设置日历需要显示的时间
我们改变日历显示的月份,也是通过这个方法来改变
//在日历显示初始化的时候就需要
[self.calendarManager setDate:[NSDate date]];
5.设置选中的日期
在控制器内我们可以创建一个结构体,用来做日历的数据源
{
//有事件的时间数组,我暂时没用到
NSMutableDictionary *_eventsByDate;
//选中的时间数组,添加时间到这个数组里则可以显示红圈,也就是选中状态
NSMutableArray *_datesSelected;
//设置选中的模式,YES是选中模式,NO是全部不选中。
BOOL _selectionMode;
}
6.刷新数据源并显示日期
//完成上面的设置后就可以进行数据刷新,显示日历了,类似TablView的刷新
[self ReloadDateTitle];
7.自定义样式
改变日历的样式,可以通过成为Manager的代理,通过代理方法进行修改,也可以通过直接暴力修改框架,来达到目的,这次我两种方式都使用到了
//成为管理者的代理,并遵守协议
self.calendarManager.delegate = self;
//改变日历的代理方法
- (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
{
//日期为今天的样式
if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
dayView.circleView.hidden = NO;
dayView.circleView.backgroundColor = RGBA(172, 176, 177, 1);
dayView.dotView.backgroundColor = [UIColor whiteColor];
dayView.textLabel.textColor = [UIColor whiteColor];
}
//日期为选中模式的样式
else if([self isInDatesSelected:dayView.date]){
dayView.circleView.hidden = NO;
dayView.circleView.backgroundColor = RGBA(227, 114, 127, 1);
dayView.dotView.backgroundColor = [UIColor whiteColor];
dayView.textLabel.textColor = [UIColor whiteColor];
}
//这个为本月内第一个星期里上月日期的样式
else if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
dayView.circleView.hidden = YES;
dayView.dotView.backgroundColor = [UIColor redColor];
dayView.textLabel.textColor = [UIColor lightGrayColor];
}
// 这个为下月内第一个星期里今天的样式
else{
dayView.circleView.hidden = YES;
dayView.dotView.backgroundColor = [UIColor redColor];
dayView.textLabel.textColor = [UIColor blackColor];
}
//日期有事件则显示个小红点,没有就不显示
if([self haveEventForDay:dayView.date]){
dayView.dotView.hidden = NO;
}
else{
dayView.dotView.hidden = YES;
}
}
上面是通过代理方法来改掉天数的样式,在项目里显示星期数需要中英文都显示,框架内只显示英文,如果需要改成我上面显示的中英文,就需要直接暴力修改框架了。
//通过查看UI图层可以知道显示周的View的类就是JTCalendarWeekDayView,我们就进JTCalendarWeekDayView里面进行修改
//首先查看他的layoutSubviews,因为子控件的布局都在这里
- (void)layoutSubviews
{
[super layoutSubviews];
//可以看到他的子控需要的数据都在这个数组里
if(!_dayViews){
return;
}
CGFloat x = 0;
CGFloat dayWidth = self.frame.size.width / NUMBER_OF_DAY_BY_WEEK;
CGFloat dayHeight = self.frame.size.height / 2;
CGFloat ChineseY = 0;
CGFloat dayY = self.frame.size.height / 2;
for(UIView *dayView in _dayViews){
dayView.frame = CGRectMake(x, dayY, dayWidth, dayHeight);
x += dayWidth;
}
}
可以看到他的布局方式是通过for循环进行的等宽高布局,所以我们也可以直接在layoutSubviews里添加自己的View来打到暴力修改的目的,很简单吧,我的代码就不上了,大家需要什么样的样式就在里面直接改就可以了,同理,DayView也是这样。
8.通过按钮来控制显示的月份
月份控制我是通过计算月份,然后设置Date刷新数据来实现的,也许有更高的办法,也可以在下方留言。
//首选我会在初始化日历控件的时候记录当前显示的时间
@property (strong, nonatomic) NSDate *Recordtime;
//初始化记录的时间
self.Recordtime = [NSDate date];
//然后在点击事件里进行时间的计算
- (IBAction)NextPageBtnClick:(id)sender {
//通过系统的日历类来计算时间
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comps = nil;
//设置需要变更的时间,年,月,日,
comps = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:self.Recordtime];
NSDateComponents *adcomps = [[NSDateComponents alloc] init];
//因为我们只需要切换月份,所有直接把月数+1就可,其他为0
[adcomps setYear:0];
[adcomps setMonth:+1];
[adcomps setDay:0];
//获得增加后的时间并记录起来
self.Recordtime = [calendar dateByAddingComponents:adcomps toDate:_Recordtime options:0];
//设置日历当前显示的时间
[self.calendarManager setDate:self.Recordtime];
//刷新日历
[self ReloadDateTitle];
}
9.总结
这个日历框架还是很方便实用的,在需要日历的项目里可以很方便的集成以及更改成自己需要的样式,每次多用一种框架就越感到自己什么都不会,大神是在太多了,学无止境,仅以自勉!