参考:https://github.com/CoderZYWang/WZYCalendar
#import <UIKit/UIKit.h>
@interface AppDelegate :UIResponder <UIApplicationDelegate>
@property (strong,nonatomic)UIWindow *window;
@end
*****************
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindowalloc]initWithFrame:[UIScreenmainScreen].bounds];
ViewController *vc = [[ViewControlleralloc]init];
UINavigationController *nav = [[UINavigationControlleralloc]initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.windowmakeKeyAndVisible];
returnYES;
}
++++++++
#import <UIKit/UIKit.h>
@interface PushController : UIViewController
@property (nonatomic,copy)NSString *titles;
@end
+++++++++++
#import "PushController.h"
@interface PushController ()
@end
@implementation PushController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title =self.titles;
self.view.backgroundColor = [UIColorcyanColor];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
++++++++#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
+++++++++++
#import "ViewController.h"
#import "PushController.h"
#import "WZYCalendar.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
self.title =@"WZYCalendar";
self.view.backgroundColor = [UIColorwhiteColor];
[selfsetupCalendar];//初始化日历对象
}
- (void)setupCalendar {
CGFloat width =self.view.bounds.size.width - 20.0;
CGPoint origin =CGPointMake(10.0, 64.0 + 80.0);
// 传入Calendar的origin和width。自动计算控件高度
WZYCalendarView *calendar = [[WZYCalendarViewalloc]initWithFrameOrigin:originwidth:width];
NSLog(@"height --- %lf", calendar.frame.size.height);
// 点击某一天的回调
calendar.didSelectDayHandler = ^(NSInteger year,NSInteger month, NSInteger day) {
PushController *pvc = [[PushControlleralloc]init];
pvc.titles = [NSStringstringWithFormat:@"%ld年%ld月%ld日", year, month, day];
[self.navigationControllerpushViewController:pvcanimated:YES];
};
[self.viewaddSubview:calendar];
}
@end
+++++++++++++
#ifndef WZYCalendar_h
#define WZYCalendar_h
#import "WZYCalendarView.h"
#endif /* WZYCalendar_h */
+++++++++++++
#import <UIKit/UIKit.h>
@interface WZYCalendarCell :UICollectionViewCell
@property (nonatomic,strong)UIView *todayCircle;//!<标示'今天'
@property (nonatomic,strong)UILabel *todayLabel;//!<标示日期(几号)
@property (nonatomic,strong)UIView *pointView;//!<标示该天具备提醒
@end
+++++++++++++++#import "WZYCalendarCell.h"
@implementation WZYCalendarCell
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [superinitWithFrame:frame]) {
// 标识当天的背景圈圈
[selfaddSubview:self.todayCircle];
// 当天的日期数字
[selfaddSubview:self.todayLabel];
// 提醒标记点
// [self addSubview:self.pointView];
}
returnself;
}
- (UIView *)todayCircle {
if (_todayCircle ==nil) {
_todayCircle = [[UIViewalloc]initWithFrame:CGRectMake(0.0, 0.0, 0.8 *self.bounds.size.height, 0.8 * self.bounds.size.height)];
_todayCircle.center =CGPointMake(0.5 *self.bounds.size.width, 0.5 * self.bounds.size.height);
_todayCircle.layer.cornerRadius = 0.5 *_todayCircle.frame.size.width;
}
return_todayCircle;
}
- (UILabel *)todayLabel {
if (_todayLabel ==nil) {
_todayLabel = [[UILabelalloc]initWithFrame:self.bounds];
_todayLabel.textAlignment =NSTextAlignmentCenter;
_todayLabel.font = [UIFontfontWithName:@"PingFang SC"size:15];
_todayLabel.backgroundColor = [UIColorclearColor];
}
return_todayLabel;
}
- (UIView *)pointView {
if (_pointView ==nil) {
_pointView = [[UIViewalloc]initWithFrame:CGRectMake(self.bounds.size.width - 4 - 2, 2, 4, 4)];
_pointView.layer.cornerRadius = 2;
_pointView.backgroundColor = [UIColorredColor];
}
return_pointView;
}
@end
++++++++++++++++++
#import <Foundation/Foundation.h>
@interface WZYCalendarMonth : NSObject
@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;//!<当前月份
@property (nonatomic,assign)NSInteger day;//!<当前日期
- (instancetype)initWithDate:(NSDate *)date;
@end
++++++++
#import "WZYCalendarMonth.h"
#import "NSDate+WZYCalendar.h"
@implementation WZYCalendarMonth
- (instancetype)initWithDate:(NSDate *)date {
if (self = [superinit]) {
_monthDate = date;
_totalDays = [selfsetupTotalDays];
_firstWeekday = [selfsetupFirstWeekday];
_year = [selfsetupYear];
_month = [selfsetupMonth];
_day = [selfsetupDay];
}
returnself;
}
/** 返回传入日期是当月的哪一天(第几天) */
- (NSInteger)setupTotalDays {
return [_monthDatetotalDaysInMonth];
}
/** 返回传入日期所在月份的第一天是周几 */
- (NSInteger)setupFirstWeekday {
return [_monthDatefirstWeekDayInMonth];
}
/** 返回传入日期的所在年 */
- (NSInteger)setupYear {
return [_monthDatedateYear];
}
/** 返回传入日期的所在月 */
- (NSInteger)setupMonth {
return [_monthDatedateMonth];
}
/** 返回传入日期的所在日 */
- (NSInteger)setupDay {
return [_monthDatedateDay];
}
@end
++++++++++++
#import <Foundation/Foundation.h>
@interface NSDate (WZYCalendar)
/**
* 获得当前 NSDate对象对应的日子
*/
- (NSInteger)dateDay;
/**
* 获得当前 NSDate对象对应的月份
*/
- (NSInteger)dateMonth;
/**
* 获得当前 NSDate对象对应的年份
*/
- (NSInteger)dateYear;
/**
* 获得当前 NSDate对象的上个月的某一天(此处定为15号)的 NSDate对象
*/
- (NSDate *)previousMonthDate;
/**
* 获得当前 NSDate对象的下个月的某一天(此处定为15号)的 NSDate对象
*/
- (NSDate *)nextMonthDate;
/**
* 获得当前 NSDate对象对应的月份的总天数
*/
- (NSInteger)totalDaysInMonth;
/**
* 获得当前 NSDate对象对应月份当月第一天的所属星期
*/
- (NSInteger)firstWeekDayInMonth;
@end
++++++++++++
#import "NSDate+WZYCalendar.h"
@implementation NSDate (WZYCalendar)
- (NSInteger)dateDay {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:NSCalendarUnitDayfromDate:self];
return components.day;
}
- (NSInteger)dateMonth {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:NSCalendarUnitMonthfromDate:self];
return components.month;
}
- (NSInteger)dateYear {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:NSCalendarUnitYearfromDate:self];
return components.year;
}
- (NSDate *)previousMonthDate {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:(NSCalendarUnitYear |NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:self];
components.day = 15;//定位到当月中间日子
if (components.month == 1) {
components.month = 12;
components.year -= 1;
} else {
components.month -= 1;
}
NSDate *previousDate = [calendardateFromComponents:components];
return previousDate;
}
- (NSDate *)nextMonthDate {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:(NSCalendarUnitYear |NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:self];
components.day = 15;//定位到当月中间日子
if (components.month == 12) {
components.month = 1;
components.year += 1;
} else {
components.month += 1;
}
NSDate *nextDate = [calendardateFromComponents:components];
return nextDate;
}
- (NSInteger)totalDaysInMonth {
NSInteger totalDays = [[NSCalendarcurrentCalendar]rangeOfUnit:NSCalendarUnitDayinUnit:NSCalendarUnitMonthforDate:self].length;
return totalDays;
}
- (NSInteger)firstWeekDayInMonth {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:(NSCalendarUnitYear |NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:self];
components.day = 1;//定位到当月第一天
NSDate *firstDay = [calendardateFromComponents:components];
// 默认一周第一天序号为 1,而日历中约定为 0,故需要减一
NSInteger firstWeekday = [calendarordinalityOfUnit:NSCalendarUnitWeekdayinUnit:NSCalendarUnitWeekOfMonthforDate:firstDay] - 1;
return firstWeekday;
}
@end
+++++++++++++
#import <UIKit/UIKit.h>
// 定义回调Block
typedef void (^DidSelectDayHandler)(NSInteger,NSInteger,NSInteger);
@interface WZYCalendarScrollView :UIScrollView
@property (nonatomic,copy)DidSelectDayHandler didSelectDayHandler;//日期点击回调
- (void)refreshToCurrentMonth;//刷新 calendar回到当前日期月份
@end
++++++++
#import "WZYCalendarScrollView.h"
#import "WZYCalendarCell.h"
#import "WZYCalendarMonth.h"
#import "NSDate+WZYCalendar.h"
@interface WZYCalendarScrollView () <UICollectionViewDataSource,UICollectionViewDelegate>
@property (nonatomic,strong)UICollectionView *collectionViewL;
@property (nonatomic,strong)UICollectionView *collectionViewM;
@property (nonatomic,strong)UICollectionView *collectionViewR;
// 当天(当前月当天)
@property (nonatomic,strong)NSDate *currentMonthDate;
@property (nonatomic,strong)NSMutableArray *monthArray;
@end
@implementation WZYCalendarScrollView
#define CURRENTHEXCOLOR(hex) [UIColor colorWithRed:((float)((hex &0xFF0000) >>16)) /255.0 green:((float)((hex &0xFF00) >>8)) /255.0 blue:((float)(hex &0xFF)) /255.0 alpha:1]
static NSString *const kCellIdentifier =@"cell";
#pragma mark - Initialiaztion
- (instancetype)initWithFrame:(CGRect)frame {
if ([superinitWithFrame:frame]) {
self.backgroundColor = [UIColorclearColor];
self.showsHorizontalScrollIndicator =NO;
self.showsVerticalScrollIndicator =NO;
self.pagingEnabled =YES;
self.bounces =NO;
self.delegate =self;
self.contentSize =CGSizeMake(3 *self.bounds.size.width,self.bounds.size.height);
[selfsetContentOffset:CGPointMake(self.bounds.size.width, 0.0) animated:NO];
_currentMonthDate = [NSDatedate];
[selfsetupCollectionViews];
}
returnself;
}
- (NSMutableArray *)monthArray {
if (_monthArray ==nil) {
_monthArray = [NSMutableArrayarrayWithCapacity:4];
// 上一个月的当天
NSDate *previousMonthDate = [_currentMonthDatepreviousMonthDate];
// 下一个月的当天
NSDate *nextMonthDate = [_currentMonthDatenextMonthDate];
[_monthArrayaddObject:[[WZYCalendarMonthalloc]initWithDate:previousMonthDate]];
[_monthArrayaddObject:[[WZYCalendarMonthalloc]initWithDate:_currentMonthDate]];
[_monthArrayaddObject:[[WZYCalendarMonthalloc]initWithDate:nextMonthDate]];
[_monthArrayaddObject:[selfpreviousMonthDaysForPreviousDate:previousMonthDate]];//存储左边的月份的前一个月份的天数,用来填充左边月份的首部(这里获取的其实是当前月的上上个月)
// 发通知,更改当前月份标题
[selfnotifyToChangeCalendarHeader];
}
return_monthArray;
}
- (NSNumber *)previousMonthDaysForPreviousDate:(NSDate *)date {
// 传入date,然后拿到date的上个月份的总天数
return [[NSNumberalloc]initWithInteger:[[datepreviousMonthDate]totalDaysInMonth]];
}
- (void)setupCollectionViews {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayoutalloc]init];
flowLayout.itemSize =CGSizeMake(self.bounds.size.width / 7.0, self.bounds.size.width / 7.0 * 0.85);
flowLayout.minimumLineSpacing = 0.0;
flowLayout.minimumInteritemSpacing = 0.0;
CGFloat selfWidth =self.bounds.size.width;
CGFloat selfHeight =self.bounds.size.height;
// 设置三个 collectionView,一次性加载三个 collectionView 的数据
_collectionViewL = [[UICollectionViewalloc]initWithFrame:CGRectMake(0.0, 0.0, selfWidth, selfHeight)collectionViewLayout:flowLayout];
_collectionViewL.dataSource =self;
_collectionViewL.delegate =self;
_collectionViewL.backgroundColor = [UIColorclearColor];
[_collectionViewLregisterClass:[WZYCalendarCellclass]forCellWithReuseIdentifier:kCellIdentifier];
[selfaddSubview:_collectionViewL];
_collectionViewM = [[UICollectionViewalloc]initWithFrame:CGRectMake(selfWidth, 0.0, selfWidth, selfHeight)collectionViewLayout:flowLayout];
_collectionViewM.dataSource =self;
_collectionViewM.delegate =self;
_collectionViewM.backgroundColor = [UIColorclearColor];
[_collectionViewMregisterClass:[WZYCalendarCellclass]forCellWithReuseIdentifier:kCellIdentifier];
[selfaddSubview:_collectionViewM];
_collectionViewR = [[UICollectionViewalloc]initWithFrame:CGRectMake(2 * selfWidth, 0.0, selfWidth, selfHeight)collectionViewLayout:flowLayout];
_collectionViewR.dataSource =self;
_collectionViewR.delegate =self;
_collectionViewR.backgroundColor = [UIColorclearColor];
[_collectionViewRregisterClass:[WZYCalendarCellclass]forCellWithReuseIdentifier:kCellIdentifier];
[selfaddSubview:_collectionViewR];
}
#pragma mark -
/** 滚动日历主体后拼接修改的顶部年月条显示数据并发出通知进行修改 */
- (void)notifyToChangeCalendarHeader {
WZYCalendarMonth *currentMonthInfo =self.monthArray[1];
NSMutableDictionary *userInfo = [NSMutableDictionarydictionaryWithCapacity:2];
[userInfo setObject:[[NSNumberalloc]initWithInteger:currentMonthInfo.year]forKey:@"year"];
[userInfo setObject:[[NSNumberalloc]initWithInteger:currentMonthInfo.month]forKey:@"month"];
NSNotification *notify = [[NSNotificationalloc]initWithName:@"ChangeCalendarHeaderNotification"object:niluserInfo:userInfo];
[[NSNotificationCenterdefaultCenter]postNotification:notify];
}
- (void)refreshToCurrentMonth {
// 如果现在就在当前月份,则不执行操作
WZYCalendarMonth *currentMonthInfo =self.monthArray[1];
if ((currentMonthInfo.month == [[NSDatedate]dateMonth]) && (currentMonthInfo.year == [[NSDatedate]dateYear])) {
return;
}
_currentMonthDate = [NSDatedate];
NSDate *previousMonthDate = [_currentMonthDatepreviousMonthDate];
NSDate *nextMonthDate = [_currentMonthDatenextMonthDate];
[self.monthArrayremoveAllObjects];
[self.monthArrayaddObject:[[WZYCalendarMonthalloc]initWithDate:previousMonthDate]];
[self.monthArrayaddObject:[[WZYCalendarMonthalloc]initWithDate:_currentMonthDate]];
[self.monthArrayaddObject:[[WZYCalendarMonthalloc]initWithDate:nextMonthDate]];
[self.monthArrayaddObject:[selfpreviousMonthDaysForPreviousDate:previousMonthDate]];
// 刷新数据
[_collectionViewMreloadData];
[_collectionViewLreloadData];
[_collectionViewRreloadData];
}
#pragma mark - UICollectionDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 42;// 7 * 6
}
- (__kindofUICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
WZYCalendarCell *cell = [collectionViewdequeueReusableCellWithReuseIdentifier:kCellIdentifierforIndexPath:indexPath];
if (collectionView ==_collectionViewL) {// 上一个月展示数据
WZYCalendarMonth *monthInfo =self.monthArray[0];
NSInteger firstWeekday = monthInfo.firstWeekday;//该月第一天是星期几
NSInteger totalDays = monthInfo.totalDays;//该月有几天
// 当前月
if (indexPath.row >= firstWeekday && indexPath.row < firstWeekday + totalDays) {
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)indexPath.row - (int)firstWeekday + 1];
cell.todayLabel.textColor = [UIColorcolorWithWhite:0alpha:0.87];
// 标识今天
if ((monthInfo.month == [[NSDatedate]dateMonth]) && (monthInfo.year == [[NSDatedate]dateYear])) {
if (indexPath.row == [[NSDatedate]dateDay] + firstWeekday - 1) {
cell.todayCircle.backgroundColor =CURRENTHEXCOLOR(0xFF5A39);
cell.todayLabel.textColor = [UIColorwhiteColor];
} else {
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
} else {
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
}
// 补上前后月的日期,淡色显示
elseif (indexPath.row < firstWeekday) {
int totalDaysOflastMonth = [self.monthArray[3]intValue];
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", totalDaysOflastMonth - ((int)firstWeekday - (int)indexPath.row) + 1];
cell.todayLabel.textColor =CURRENTHEXCOLOR(0xADADAD);
cell.todayCircle.backgroundColor = [UIColorclearColor];
} elseif (indexPath.row >= firstWeekday + totalDays) {
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)indexPath.row - (int)firstWeekday - (int)totalDays + 1];
cell.todayLabel.textColor =CURRENTHEXCOLOR(0xADADAD);
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
cell.userInteractionEnabled =NO;
} elseif (collectionView ==_collectionViewM) { //当前月的展示数据
WZYCalendarMonth *monthInfo =self.monthArray[1];
// 当前日期所在月份第一天是周几
NSInteger firstWeekday = monthInfo.firstWeekday;
// 当前日期是所在月份的第几天
NSInteger totalDays = monthInfo.totalDays;
// 当前月
if (indexPath.row >= firstWeekday && indexPath.row < firstWeekday + totalDays) {
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)indexPath.row - (int)firstWeekday + 1];
cell.todayLabel.textColor = [UIColorcolorWithWhite:0alpha:0.87];
cell.userInteractionEnabled =YES;
// 标识今天
if ((monthInfo.month == [[NSDatedate]dateMonth]) && (monthInfo.year == [[NSDatedate]dateYear])) {
if (indexPath.row == [[NSDatedate]dateDay] + firstWeekday - 1) {
cell.todayCircle.backgroundColor =CURRENTHEXCOLOR(0xFF5A39);
cell.todayLabel.textColor = [UIColorwhiteColor];
} else {
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
} else {
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
}
// 补上前后月的日期,淡色显示
elseif (indexPath.row < firstWeekday) {
WZYCalendarMonth *lastMonthInfo =self.monthArray[0];
NSInteger totalDaysOflastMonth = lastMonthInfo.totalDays;
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)totalDaysOflastMonth - ((int)firstWeekday - (int)indexPath.row) + 1];
cell.todayLabel.textColor =CURRENTHEXCOLOR(0xADADAD);
cell.todayCircle.backgroundColor = [UIColorclearColor];
cell.userInteractionEnabled =NO;
} elseif (indexPath.row >= firstWeekday + totalDays) {
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)indexPath.row - (int)firstWeekday - (int)totalDays + 1];
cell.todayLabel.textColor =CURRENTHEXCOLOR(0xADADAD);
cell.todayCircle.backgroundColor = [UIColorclearColor];
cell.userInteractionEnabled =NO;
}
} elseif (collectionView ==_collectionViewR) { //下一个月的展示数据
WZYCalendarMonth *monthInfo =self.monthArray[2];
NSInteger firstWeekday = monthInfo.firstWeekday;
NSInteger totalDays = monthInfo.totalDays;
// 当前月
if (indexPath.row >= firstWeekday && indexPath.row < firstWeekday + totalDays) {
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)indexPath.row - (int)firstWeekday + 1];
cell.todayLabel.textColor = [UIColorcolorWithWhite:0alpha:0.87];
// 标识今天
if ((monthInfo.month == [[NSDatedate]dateMonth]) && (monthInfo.year == [[NSDatedate]dateYear])) {
if (indexPath.row == [[NSDatedate]dateDay] + firstWeekday - 1) {
cell.todayCircle.backgroundColor =CURRENTHEXCOLOR(0xFF5A39);
cell.todayLabel.textColor = [UIColorwhiteColor];
} else {
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
} else {
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
// 补上前后月的日期,淡色显示
} elseif (indexPath.row < firstWeekday) {
WZYCalendarMonth *lastMonthInfo =self.monthArray[1];
NSInteger totalDaysOflastMonth = lastMonthInfo.totalDays;
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)totalDaysOflastMonth - ((int)firstWeekday - (int)indexPath.row) + 1];
cell.todayLabel.textColor =CURRENTHEXCOLOR(0xADADAD);
cell.todayCircle.backgroundColor = [UIColorclearColor];
} elseif (indexPath.row >= firstWeekday + totalDays) {
cell.todayLabel.text = [NSStringstringWithFormat:@"%d", (int)indexPath.row - (int)firstWeekday - (int)totalDays + 1];
cell.todayLabel.textColor =CURRENTHEXCOLOR(0xADADAD);
cell.todayCircle.backgroundColor = [UIColorclearColor];
}
cell.userInteractionEnabled =NO;
}
return cell;
}
#pragma mark - UICollectionViewDeleagate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (self.didSelectDayHandler != nil) {
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSDateComponents *components = [calendarcomponents:(NSCalendarUnitYear |NSCalendarUnitMonth) fromDate:_currentMonthDate];
NSDate *currentDate = [calendardateFromComponents:components];
WZYCalendarCell *cell = (WZYCalendarCell *)[collectionViewcellForItemAtIndexPath:indexPath];
NSInteger year = [currentDatedateYear];
NSInteger month = [currentDatedateMonth];
NSInteger day = [cell.todayLabel.textintegerValue];
self.didSelectDayHandler(year, month, day);//执行回调(将点击的日期cell上面的信息回调出去)
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView !=self) {
return;
}
/**
注意:当前月份当前天 ==现在这一天 当前显示月份 ==当前界面上显示的那个月份
假设当天为 2016年12月22日那么当前显示的日历为 11月 | 12月 | 1月
在上面这个假设的基础上我们进行滑动操作
原本的monthArray = [11月monthInfo, 12月monthInfo, 1月monthInfo, 10月份天数];
说明一下:为什么要传入10月份的天数,因为左侧显示部分会带有10月份后面几天,而1月份后面显示的会有2月份的前几天。由于每个月前几天是确定的,而后几天不确定,所以说数组中要加上这么一个参数。
*/
// 向右滑动
if (scrollView.contentOffset.x <self.bounds.size.width) {
_currentMonthDate = [_currentMonthDatepreviousMonthDate];// currentMonthDate 11月15日(向右滑动之后,原本显示在左侧的上个月就变成了当前显示的月份,原本的_currentMonthDate是当前月份当前天,但是向右滑动之后就变成了左侧月份的15号这一天)
NSDate *previousDate = [_currentMonthDatepreviousMonthDate];// previousDate 10月15日(又进行了一次取前一月份15日的操作,在上面一句的基础上)
// 取数组中的值(该数组还是滑动之前的)
WZYCalendarMonth *currentMothInfo =self.monthArray[0];// currentMothInfo 11月
WZYCalendarMonth *nextMonthInfo =self.monthArray[1];// nextMonthInfo 12月
WZYCalendarMonth *olderNextMonthInfo =self.monthArray[2];// olderNextMonthInfo 1月
// 复用 WZYCalendarMonth对象
olderNextMonthInfo.totalDays = [previousDatetotalDaysInMonth];//
olderNextMonthInfo.firstWeekday = [previousDatefirstWeekDayInMonth];//
olderNextMonthInfo.year = [previousDatedateYear];//
olderNextMonthInfo.month = [previousDatedateMonth];//
WZYCalendarMonth *previousMonthInfo = olderNextMonthInfo;// previousMonthInfo == olderNextMonthInfo == 10月份信息
NSNumber *prePreviousMonthDays = [selfpreviousMonthDaysForPreviousDate:[_currentMonthDatepreviousMonthDate]];// prePreviousMonthDays 拿到9月份的天数(后面的传值是10月15日)
[self.monthArrayremoveAllObjects];
[self.monthArrayaddObject:previousMonthInfo];
[self.monthArrayaddObject:currentMothInfo];
[self.monthArrayaddObject:nextMonthInfo];
[self.monthArrayaddObject:prePreviousMonthDays];
// 新的 monthArray = [10月monthInfo, 11月monthInfo, 12月monthInfo, 9月份天数];
}
// 向左滑动
elseif (scrollView.contentOffset.x >self.bounds.size.width) {
_currentMonthDate = [_currentMonthDatenextMonthDate];
NSDate *nextDate = [_currentMonthDatenextMonthDate];
// 数组中最右边的月份现在作为中间的月份,中间的作为左边的月份,新的右边的需要重新获取
WZYCalendarMonth *previousMonthInfo =self.monthArray[1];
WZYCalendarMonth *currentMothInfo =self.monthArray[2];
WZYCalendarMonth *olderPreviousMonthInfo =self.monthArray[0];
NSNumber *prePreviousMonthDays = [[NSNumberalloc]initWithInteger:olderPreviousMonthInfo.totalDays];//先保存 olderPreviousMonthInfo的月天数
// 复用 WZYCalendarMonth对象
olderPreviousMonthInfo.totalDays = [nextDatetotalDaysInMonth];
olderPreviousMonthInfo.firstWeekday = [nextDatefirstWeekDayInMonth];
olderPreviousMonthInfo.year = [nextDatedateYear];
olderPreviousMonthInfo.month = [nextDatedateMonth];
WZYCalendarMonth *nextMonthInfo = olderPreviousMonthInfo;
[self.monthArrayremoveAllObjects];
[self.monthArrayaddObject:previousMonthInfo];
[self.monthArrayaddObject:currentMothInfo];
[self.monthArrayaddObject:nextMonthInfo];
[self.monthArrayaddObject:prePreviousMonthDays];
}
[_collectionViewMreloadData];//中间的 collectionView先刷新数据
[scrollView setContentOffset:CGPointMake(self.bounds.size.width, 0.0) animated:NO];//然后变换位置
[_collectionViewLreloadData];//最后两边的 collectionView也刷新数据
[_collectionViewRreloadData];
// 发通知,更改当前月份标题
[selfnotifyToChangeCalendarHeader];
}
@end
+++++++++++++
#import <UIKit/UIKit.h>
// 回调 block
typedef void (^DidSelectDayHandler)(NSInteger,NSInteger,NSInteger);
@interface WZYCalendarView : UIView
/**
* 构造方法
*
* @param origin calendar的位置
* @param width calendar的宽度(高度会根据给定的宽度自动计算)
*
* @return bannerView对象
*/
- (instancetype)initWithFrameOrigin:(CGPoint)origin width:(CGFloat)width;
/**
* calendar 的高度(只读属性)
*/
@property (nonatomic,assign,readonly)CGFloat calendarHeight;
/**
* 日期点击回调
* block 的参数表示当前日期的 NSDate对象
*/
@property (nonatomic,copy)DidSelectDayHandler didSelectDayHandler;
@end
++++++++++
#import "WZYCalendarView.h"
#import "WZYCalendarScrollView.h"
#import "NSDate+WZYCalendar.h"
@interface WZYCalendarView()
/** 顶部条年-月 &&今 */
@property (nonatomic,strong)UIView *topYearMonthView;
/** 顶部条 “2016年 12月” button */
@property (nonatomic,strong)UIButton *calendarHeaderButton;
/** 顶部条 “今” button */
@property (nonatomic,strong)UIButton *todayButton;
/** 星期条 */
@property (nonatomic,strong)UIView *weekHeaderView;
/** 日历主体 */
@property (nonatomic,strong)WZYCalendarScrollView *calendarScrollView;
@end
#define HEXCOLOR(hex) [UIColor colorWithRed:((float)((hex & 0xFF0000) >> 16)) /255.0 green:((float)((hex &0xFF00) >> 8)) /255.0 blue:((float)(hex &0xFF)) /255.0 alpha:1]
@implementation WZYCalendarView
#pragma mark - Initialization
- (instancetype)initWithFrameOrigin:(CGPoint)origin width:(CGFloat)width {
// 根据宽度计算 calender主体部分的高度
CGFloat weekLineHight = 0.85 * (width / 7.0);// 一行的高度
CGFloat monthHeight = 6 * weekLineHight;//主体部分整体高度
// 星期头部栏高度
CGFloat weekHeaderHeight = weekLineHight;
// calendar 头部栏高度
CGFloat calendarHeaderHeight = weekLineHight;
// 最后得到整个 calender控件的高度
_calendarHeight = calendarHeaderHeight + weekHeaderHeight + monthHeight;
if (self = [superinitWithFrame:CGRectMake(origin.x, origin.y, width, _calendarHeight)]) {
self.layer.masksToBounds =YES;
// 整体边框颜色
self.layer.borderColor =HEXCOLOR(0xEEEEEE).CGColor;
self.layer.borderWidth = 2.0 / [UIScreenmainScreen].scale;
self.layer.cornerRadius = 8.0;
// 顶部 2016年12月按钮单击跳转到当前月份
_topYearMonthView = [selfsetupCalendarHeaderWithFrame:CGRectMake(0.0, 0.0, width, calendarHeaderHeight)];
// 顶部日一二三四五六 label星期条
_weekHeaderView = [selfsetupWeekHeadViewWithFrame:CGRectMake(0.0, calendarHeaderHeight, width, weekHeaderHeight)];
// 底部月历滚动scroll
_calendarScrollView = [selfsetupCalendarScrollViewWithFrame:CGRectMake(0.0, calendarHeaderHeight + weekHeaderHeight, width, monthHeight)];
[selfaddSubview:_topYearMonthView];
[selfaddSubview:_weekHeaderView];
[selfaddSubview:_calendarScrollView];
// 注册 Notification监听
[selfaddNotificationObserver];
}
returnself;
}
- (void)dealloc {
// 移除监听
[[NSNotificationCenterdefaultCenter]removeObserver:self];
}
/** 设置顶部条,显示年-月的 */
- (UIView *)setupCalendarHeaderWithFrame:(CGRect)frame {
UIView *backView = [[UIViewalloc]initWithFrame:frame];
backView.backgroundColor =HEXCOLOR(0xF6F6F6);
UIButton *yearMonthButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
_calendarHeaderButton = yearMonthButton;
yearMonthButton.frame =CGRectMake(0, 0, 120, frame.size.height);
yearMonthButton.backgroundColor = [UIColorclearColor];
[yearMonthButton setTitleColor:HEXCOLOR(0xFF5A39)forState:UIControlStateNormal];
[yearMonthButton.titleLabelsetFont:[UIFontfontWithName:@"PingFang SC"size:16]];
[backView addSubview:yearMonthButton];
UIButton *todayButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
todayButton.frame =CGRectMake(frame.size.width - frame.size.height, 7, frame.size.height - 14, frame.size.height - 14);
[todayButton setTitle:@"今"forState:UIControlStateNormal];
[todayButton setTitleColor:[UIColorwhiteColor]forState:UIControlStateNormal];
todayButton.backgroundColor =HEXCOLOR(0xFF5A39);
todayButton.layer.cornerRadius = todayButton.frame.size.width * 0.5;
[todayButton addTarget:selfaction:@selector(refreshToCurrentMonthAction:)forControlEvents:UIControlEventTouchUpInside];
[backView addSubview:todayButton];
return backView;
}
/** 设置星期条,显示日一二 ...五六 */
- (UIView *)setupWeekHeadViewWithFrame:(CGRect)frame {
CGFloat height = frame.size.height;
CGFloat width = frame.size.width / 7.0;
UIView *view = [[UIViewalloc]initWithFrame:frame];
// view.backgroundColor = HEXCOLOR(0xF6F6F6);
view.backgroundColor = [UIColorwhiteColor];
NSArray *weekArray = @[@"日",@"一",@"二",@"三",@"四",@"五",@"六"];
for (int i = 0; i < 7; ++i) {
UILabel *label = [[UILabelalloc]initWithFrame:CGRectMake(i * width, 0.0, width, height)];
label.backgroundColor = [UIColorclearColor];
label.text = weekArray[i];
if ([label.textisEqualToString:@"日"] || [label.text isEqualToString:@"六"]) {
label.textColor =HEXCOLOR(0xADADAD);
} else {
label.textColor = [UIColorcolorWithWhite:0alpha:0.87];
}
label.font = [UIFontfontWithName:@"PingFang SC"size:13.5];
label.textAlignment =NSTextAlignmentCenter;
[view addSubview:label];
}
return view;
}
/** 设置底部滚动日历 */
- (WZYCalendarScrollView *)setupCalendarScrollViewWithFrame:(CGRect)frame {
// 构造方法
WZYCalendarScrollView *scrollView = [[WZYCalendarScrollViewalloc]initWithFrame:frame];
return scrollView;
}
/** 重写block回调方法 */
- (void)setDidSelectDayHandler:(DidSelectDayHandler)didSelectDayHandler {
_didSelectDayHandler = didSelectDayHandler;
if (_calendarScrollView !=nil) {
_calendarScrollView.didSelectDayHandler =_didSelectDayHandler;// 传递 block(将日历中日期点击之后得到的对应数据返回给CalendarView)
// 由于_calendarScrollView的 block是由外层的 CalendarView传给他的,所以说当这个 block有回调之后,外面的 CalendarView的 block也就有了回调结果。所以说控制器就可以拿到了。这是属于指针之间的传递。
}
}
/** 添加通知的接收 */
- (void)addNotificationObserver {
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(changeCalendarHeaderAction:)name:@"ChangeCalendarHeaderNotification"object:nil];
}
#pragma mark - Actions
/** 改变顶部年月栏的日期显示 &&滚动到当前月份 */
- (void)refreshToCurrentMonthAction:(UIButton *)sender {
// 设置显示日期
NSInteger year = [[NSDatedate]dateYear];
NSInteger month = [[NSDatedate]dateMonth];
NSString *title = [NSStringstringWithFormat:@"%d年 %d月", (int)year, (int)month];
[_calendarHeaderButtonsetTitle:titleforState:UIControlStateNormal];
// 进行滑动
[_calendarScrollViewrefreshToCurrentMonth];
}
// 接收通知传递回来的数据(包装在sender.userInfo里面)
- (void)changeCalendarHeaderAction:(NSNotification *)sender {
NSDictionary *dic = sender.userInfo;
NSNumber *year = dic[@"year"];
NSNumber *month = dic[@"month"];
NSString *title = [NSStringstringWithFormat:@"%@年 %@月", year, month];
[_calendarHeaderButtonsetTitle:titleforState:UIControlStateNormal];
}
@end
=============上面是原码,下面是调用
#import "ViewController.h"
#import <WZYCalendar/WZYCalendar.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 设置尺寸
CGFloat width =self.view.bounds.size.width - 20.0;
CGPoint origin =CGPointMake(10.0, 64.0 + 80.0);
// 传入Calendar的origin和width,自动计算控件高度
WZYCalendarView *calendar = [[WZYCalendarViewalloc] initWithFrameOrigin:originwidth:width];
// 点击某一天的回调
calendar.didSelectDayHandler = ^(NSInteger year,NSInteger month, NSInteger day) {
NSLog(@"%ld年%ld月%ld日", year, month, day);
};
// 添加到控制器的view中
[self.viewaddSubview:calendar];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end