主要功能:选择日期
主要功能:操作:左滑动,左上按钮点击 下一月
主要功能:操作:右滑动,右上按钮点击 上一月
主要功能:操作:点击日期,日历消失并返回选择的日期
使用方式:
1: 默认创建显示当前日期的日历
先导入工具 #import “XMPickDataView.h”
然后调initWithPoint方法传参数:显示位置,执行代码块
XMPickDataView *dataPick = [[XMPickDataView alloc] initWithPoint:CGPointMake(100, 100) DidBlock:^(NSString *call) {
//call: 返回点击日历中的日期返回来的时间
NSLog(@"pick Date:%@",call);
}];
// 添加进本控制的self.view即可
[self.view addSubview:dataPick];
2: 根据您传进去的date创建日历
先导入工具 #import “XMPickDataView.h”
然后调initWithPoint方法传参数:显示位置,执行代码块,显示的日历日期
NSDateFormatter *getMonthDateformat = [[NSDateFormatter alloc] init];
[getMonthDateformat setDateFormat:@"YYYY年MM月dd日 hh时mm分ss秒"];
XMPickDataView *dataPick = [[XMPickDataView alloc] initWithPoint:CGPointMake(200, 200) DidBlock:^(NSString *call) {
//call: 返回点击日历中的日期返回来的时间
NSLog(@"pick Date:%@",call);
} date:[getMonthDateformat dateFromString:@"2018年1月1日 1时1分1秒"]];
// 添加进本控制的self.view即可
[self.view addSubview:dataPick];
大体就是上边的那种显示了
实现流程
1.先找两张图片,显示左右切换的日期按钮
2.创建XMDatePicker类继承自UIView
3.定义一个代码块DidBlock,并且添加一个单元格表引用 ,并且提供一个给外界的方法来创建日历
//block是代码块,用来把外界一段代码当参数传进方法执行的
这个block是给外界用的,点击日期 执行外界传进来的一段要执行的代码
collectionView 显示日期的单元表格
point: 显示日历的坐标 (x,y)
didBlock:给外界用的
date:日历显示的日期
4.在实现类里定义一些属性,这些属性是不需要外界主动赋值的
5.实现方法
- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock date:(NSDate *) date
这里的self原型是个UIView
- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock date:(NSDate *) date{
//调用父类的init方法
self = [super init];
//通过传进来的point设置view(x,y) 宽高输入固定值 (328,340) 这里的数值是我计算好的
self.frame = CGRectMake(point.x, point.y, 328, 340);
//圆角半径20
self.layer.cornerRadius = 20.0;
//设置view背景完全没有颜色, 跟透明一样 ,就是看起来好看一点把。
[self setBackgroundColor:[UIColor clearColor]];
//外界传进来的代码块让咱先拿到引用
self.didBlock = didBlock;
//流式布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
//初始化日历主要显示控件collectionView 设置坐标和宽高,因为他是咱的子控件 (x,y)是基于咱的(x,y)的
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(13, 56, 302, 276) collectionViewLayout:layout];
//注册单元格,创建单元格时要用到,因为是纯代码,没有xib文件的
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"DatePickCell"];
//设置透明颜色,跟透明一样的颜色
[self.collectionView setBackgroundColor:[UIColor clearColor]];
//让他归属咱
[self addSubview:self.collectionView];
//self.backgroundColor=[UIColor blueColor];
//拿到他的代理
self.collectionView.delegate = self;
//拿到他的数据资源
self.collectionView.dataSource = self;
//刷新
[self.collectionView reloadData];
//这里创建的时间格式 是为了获取当前年份
//科普: Y:年 M:月 d:日
NSDateFormatter *dateYearFormatter = [[NSDateFormatter alloc] init];
[dateYearFormatter setDateFormat:@"YYYY"];
NSDateFormatter *dateMonthFormatter = [[NSDateFormatter alloc] init];
[dateMonthFormatter setDateFormat:@"MM"];
//初始化标题控件titleLabel 设置坐标和宽高,因为他是咱的子控件 (x,y)是基于咱的(x,y)的
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(119, 33, 90, 16)];
//字体大小16 字体苹果苹方
[self.titleLabel setFont:[UIFont fontWithName:@"PingFangSC-Regular" size:16]];
//字体颜色
[self.titleLabel setTextColor:[UIColor colorWithRed:76.0/255.0 green:82.0/255.0 blue:70.0/255.0 alpha:1.0]];
//居中
[self.titleLabel setTextAlignment:NSTextAlignmentCenter];
//让他归属咱
[self addSubview:self.titleLabel];
//获取 年 和 月 拼接字符串 然后给标题赋值 这里的date就是外界传进来的时间
[self.titleLabel setText:[NSString stringWithFormat:@"%@年%@月",[dateYearFormatter stringFromDate:date],[dateMonthFormatter stringFromDate:date]]];
/* **/
return self;
}
6:添加方法
- (NSInteger)getMonthsDay:(NSInteger) months forYears:(NSInteger) years和
- (NSInteger)weekdayWithDate:(NSDate *)date
第一个方法通过年份和月份判断当前月份天数,第二个方法通过日期判断星期几
//第一个方法通过年份和月份判断当前月份天数
- (NSInteger)getMonthsDay:(NSInteger) months forYears:(NSInteger) years{
if ((years % 4 == 0 && years % 100 != 0) || years % 400 == 0) {
//leapMonthsDayList是闰年月天数集合
return [self.leapMonthsDayList[months-1] integerValue];
}else{
//ordinaryMonthsDayList是平年月天数集合
return [self.ordinaryMonthsDayList[months-1] integerValue];
}
}
//通过日期判断星期几
- (NSInteger)weekdayWithDate:(NSDate *)date {
//通过传进来的date创建一个时间容器
NSDateComponents *componets = [[NSCalendar autoupdatingCurrentCalendar] components:NSCalendarUnitWeekday fromDate:date];
//这里返回的是从周日到周六开始算事第几天 从1开始
NSInteger weekday = [componets weekday];
//返回的数-1,c程序员要从0开始算
return weekday-1;
}
7:创建initXMPickDate方法初始化闰年平年月天数集合,把刚刚在
- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock date:(NSDate *) date
方法中的初始化titleLabel的代码剪切过来
- (void) initXMPickDate{
self.calenderTitleList = @[@"日",@"一",@"二",@"三",@"四",@"五",@"六"];
//leapMonthsDayList是闰年月天数集合
self.leapMonthsDayList = @[@"31",@"29",@"31",@"30"
,@"31",@"30",@"31",@"31"
,@"30",@"31",@"30",@"31"];
//ordinaryMonthsDayList是平年月天数集合
self.ordinaryMonthsDayList = @[@"31",@"28",@"31",@"30"
,@"31",@"30",@"31",@"31"
,@"30",@"31",@"30",@"31"];
//初始化标题控件titleLabel 设置坐标和宽高,因为他是咱的子控件 (x,y)是基于咱的(x,y)的
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(119, 33, 90, 16)];
//字体大小16 字体苹果苹方
[self.titleLabel setFont:[UIFont fontWithName:@"PingFangSC-Regular" size:16]];
//字体颜色
[self.titleLabel setTextColor:[UIColor colorWithRed:76.0/255.0 green:82.0/255.0 blue:70.0/255.0 alpha:1.0]];
//居中
[self.titleLabel setTextAlignment:NSTextAlignmentCenter];
//让他归属咱
[self addSubview:self.titleLabel];
}
8:添加表格的代理方法
日历分为几部分
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
日历单元格上下间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
日历单元格左右边距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
日历单元格大小
- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
每个分区上的单元格个数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
初始化单元格
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
点击单元格后执行的方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 2;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 5.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 5.0;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(35,35);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if(section == 0){
// 第一部分显示的是标题
return 7;
}else{
// showMonthsDaysCount是这个月的天数 加上本月1号星期几.因为假如1号不是周日要让上月来补
return self.numberOneDayIndex + self.showMonthsDaysCount;
}
}
//初始化单元格
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// 通过上边注册的id来初始化一个单元格
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"DatePickCell" forIndexPath:indexPath];
//假如没初始化到
if (cell == nil) {
//自己init一个,起码不让程序崩溃,,,
cell = [[UICollectionViewCell alloc] init];
}
//先把这个初始化到的单元格内容全清掉
for (UIView* view in cell.contentView.subviews) {
//删除自己和父view的关系,没有人引用就会被带走,远方~~~
[view removeFromSuperview];
}
//假如这是单元格的第一部分
if (indexPath.section == 0) {
//创建一个文本
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
//通过标题列表来进行赋值
[label setText:self.calenderTitleList[indexPath.row]];
//文本内的字体居中对齐
[label setTextAlignment:NSTextAlignmentCenter];
//添加进单元格
[cell.contentView addSubview:label];
}
//假如这是单元格的第二部分
if (indexPath.section == 1) {
//假如这是单元格的第二部分要显示上个月补位的部分
if (indexPath.row < self.numberOneDayIndex) {
//创建一个文本
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
//上个月的天数减去这个月的1号星期几 加上这是第二部分几个单元格等于要显示的上个月补位日期
[label setText:[NSString stringWithFormat:@"%ld",self.backMonthsDaysCount - self.numberOneDayIndex + indexPath.row+1]];
//设置字体颜色
[label setTextColor:[UIColor colorWithRed:190.0/255.0 green:190.0/255.0 blue:190.0/255.0 alpha:1.0]];
//文本内的字体居中对齐
[label setTextAlignment:NSTextAlignmentCenter];
//添加进单元格
[cell.contentView addSubview:label];
}else{
//假如这是单元格的第二部分要显示日期的部分
//创建一个文本
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
//第二部分几个单元格减去这个月一号星期几等于要显示的这个月日期
[label setText:[NSString stringWithFormat:@"%ld",indexPath.row+1-self.numberOneDayIndex]];
//设置字体颜色
[label setTextColor:[UIColor colorWithRed:76.0/255.0 green:82.0/255.0 blue:70.0/255.0 alpha:1.0]];
//文本内的字体居中对齐
[label setTextAlignment:NSTextAlignmentCenter];
//添加进单元格
[cell.contentView addSubview:label];
}
}
//返回设置的单元格
return cell;
}
//点击单元格执行的方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
//单元格第二部分
if (indexPath.section == 1) {
if (indexPath.row < self.numberOneDayIndex) {
}else{
//显示真正日期的部分,给外界要执行的代码块传参数 选中的年月日
self.didBlock([NSString stringWithFormat:@"%@%ld日",self.titleLabel.text,indexPath.row+1-self.numberOneDayIndex]);
//删除日历的引用,日历任务完成
[self removeFromSuperview];
}
}
}
9.- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock date:(NSDate *) date
方法最下边加上给numberOneDayIndex,showMonthsDaysCount,backMonthsDaysCount的赋值
/* **/
NSDateFormatter *dateformat = [[NSDateFormatter alloc] init];
[dateformat setDateFormat:@"YYYY年MM月dd日"];
NSDate *numberOneDate = [dateformat dateFromString:[NSString stringWithFormat:@"%@年%@月1日",[dateYearFormatter stringFromDate:date],[dateMonthFormatter stringFromDate:date]]];
//给numberOneDayIndex赋值 1号星期几
self.numberOneDayIndex = [self weekdayWithDate:numberOneDate];
/* **/
//得到年
NSInteger years = [[dateYearFormatter stringFromDate:date] integerValue];
//得到月
NSInteger months = [[dateMonthFormatter stringFromDate:date] integerValue];
//通过得到的年月给showMonthsDaysCount赋值 当前显示的月份的天数
self.showMonthsDaysCount = [self getMonthsDay:months forYears:years];
//计算出上个月
if (months>1) {
months -= 1;
}else{
years -= 1;
months = 12;
}
//通过得到的年月给backMonthsDaysCount赋值 当前显示的月份的上个月的天数
self.backMonthsDaysCount = [self getMonthsDay:months forYears:years];
//刷新数据
[self.collectionView reloadData];
10.在- (void) initXMPickDate方法中添加切换月份的按钮,并添加左滑右滑动手势
//初始化左按钮
UIButton *leftBtn = [[UIButton alloc] initWithFrame:CGRectMake(83, 27, 30, 40)];
//初始化右按钮
UIButton *rightBtn = [[UIButton alloc] initWithFrame:CGRectMake(202, 27, 30, 40)];
//初始化左按钮显示的图片
UIImageView *leftImageView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 5, 13, 17)];
//初始化右按钮显示的图片
UIImageView *rightImageView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 5, 13, 17)];
//设置左按钮图片
[leftImageView setImage:[UIImage imageNamed:@"xm_back.png"]];
//设置右按钮图片
[rightImageView setImage:[UIImage imageNamed:@"xm_next.png"]];
//左按钮图片添加进左按钮
[leftBtn addSubview:leftImageView];
//右按钮图片添加进右按钮
[rightBtn addSubview:rightImageView];
//添加左按钮点击事件 并绑定方法backMonth
[leftBtn addTarget:self action:@selector(backMonth) forControlEvents:UIControlEventTouchUpInside];
//添加右按钮点击事件 并绑定方法nextMonth
[rightBtn addTarget:self action:@selector(nextMonth) forControlEvents:UIControlEventTouchUpInside];
//初始化滑动手势
UISwipeGestureRecognizer *leftGestureRecognizer = [[UISwipeGestureRecognizer alloc] init];
//设置为左滑动手势
[leftGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
//绑定方法nextMonth
[leftGestureRecognizer addTarget:self action:@selector(nextMonth)];
//给咱添加左滑动手势
[self addGestureRecognizer:leftGestureRecognizer];
//初始化滑动手势
UISwipeGestureRecognizer *rightGestureRecognizer = [[UISwipeGestureRecognizer alloc] init];
//设置为右滑动手势
[rightGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
//绑定方法backMonth
[rightGestureRecognizer addTarget:self action:@selector(backMonth)];
//给咱添加右滑动手势
[self addGestureRecognizer:rightGestureRecognizer];
//给咱添加左切换月份按钮
[self addSubview:leftBtn];
//给咱添加右切换月份按钮
[self addSubview:rightBtn];
11.实现刚刚要绑定的backMonth,nextMonth方法 切换月份主要代码
//上一个月份
-(void) backMonth{
NSDateFormatter *getMonthDateformat = [[NSDateFormatter alloc] init];
[getMonthDateformat setDateFormat:@"YYYY年MM月dd日 hh时mm分ss秒"];
NSDateFormatter *dateYearFormatter = [[NSDateFormatter alloc] init];
[dateYearFormatter setDateFormat:@"YYYY"];
NSDateFormatter *dateMonthFormatter = [[NSDateFormatter alloc] init];
[dateMonthFormatter setDateFormat:@"MM"];
//获取标题上显示的日期
NSDate *date = [getMonthDateformat dateFromString:[NSString stringWithFormat:@"%@%@",self.titleLabel.text,@"01日 0时0分0秒"]];
//获取这个日期月
NSInteger months = [[dateMonthFormatter stringFromDate:date] integerValue];
//获取这个日期年
NSInteger years = [[dateYearFormatter stringFromDate:date] integerValue];
//月份减1
if (months > 1) {
months -= 1;
}else{
years -= 1;
months = 12;
}
//重新赋值日期
date = [getMonthDateformat dateFromString:[NSString stringWithFormat:@"%ld年%ld月 01日 0时0分0秒",years,months]];
//重新赋值标题
[self.titleLabel setText:[NSString stringWithFormat:@"%@年%@月",[dateYearFormatter stringFromDate:date],[dateMonthFormatter stringFromDate:date]]];
/* **/
NSDateFormatter *dateformat = [[NSDateFormatter alloc] init];
[dateformat setDateFormat:@"YYYY年MM月dd日"];
//1号日期
NSDate *numberOneDate = [dateformat dateFromString:[NSString stringWithFormat:@"%@年%@月1日",[dateYearFormatter stringFromDate:date],[dateMonthFormatter stringFromDate:date]]];
//重新赋值1号星期几
self.numberOneDayIndex = [self weekdayWithDate:numberOneDate];
/* **/
years = [[dateYearFormatter stringFromDate:date] integerValue];
months = [[dateMonthFormatter stringFromDate:date] integerValue];
//重新赋值这个月几天
self.showMonthsDaysCount = [self getMonthsDay:months forYears:years];
if (months>1) {
months -= 1;
}else{
years -= 1;
months = 12;
}
//重新赋值这个月的上个月几天
self.backMonthsDaysCount = [self getMonthsDay:months forYears:years];
//刷新数据
[self.collectionView reloadData];
}
//下一个月份
-(void) nextMonth{
NSDateFormatter *getMonthDateformat = [[NSDateFormatter alloc] init];
[getMonthDateformat setDateFormat:@"YYYY年MM月dd日 hh时mm分ss秒"];
NSDateFormatter *dateYearFormatter = [[NSDateFormatter alloc] init];
[dateYearFormatter setDateFormat:@"YYYY"];
NSDateFormatter *dateMonthFormatter = [[NSDateFormatter alloc] init];
//获取标题上显示的日期
NSDate *date = [getMonthDateformat dateFromString:[NSString stringWithFormat:@"%@%@",self.titleLabel.text,@"01日 0时0分0秒"]];
//获取这个日期月
NSInteger months = [[dateMonthFormatter stringFromDate:date] integerValue];
//获取这个日期年
NSInteger years = [[dateYearFormatter stringFromDate:date] integerValue];
//月份加1
if (months < 12) {
months += 1;
}else{
years += 1;
months = 1;
}
//重新赋值日期
date = [getMonthDateformat dateFromString:[NSString stringWithFormat:@"%ld年%ld月 01日 0时0分0秒",years,months]];
//重新赋值标题
[self.titleLabel setText:[NSString stringWithFormat:@"%@年%@月",[dateYearFormatter stringFromDate:date],[dateMonthFormatter stringFromDate:date]]];
/* **/
NSDateFormatter *dateformat = [[NSDateFormatter alloc] init];
[dateformat setDateFormat:@"YYYY年MM月dd日"];
//1号日期
NSDate *numberOneDate = [dateformat dateFromString:[NSString stringWithFormat:@"%@年%@月1日",[dateYearFormatter stringFromDate:date],[dateMonthFormatter stringFromDate:date]]];
//重新赋值1号星期几
self.numberOneDayIndex = [self weekdayWithDate:numberOneDate];
/* **/
years = [[dateYearFormatter stringFromDate:date] integerValue];
months = [[dateMonthFormatter stringFromDate:date] integerValue];
//重新赋值这个月几天
self.showMonthsDaysCount = [self getMonthsDay:months forYears:years];
if (months>1) {
months -= 1;
}else{
years -= 1;
months = 12;
}
//重新赋值这个月的上个月几天
self.backMonthsDaysCount = [self getMonthsDay:months forYears:years];
//刷新数据
[self.collectionView reloadData];
12.提供一个方法来直接生成当前日历
- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock
//给外界提供访问链接
- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock;
- (instancetype) initWithPoint:(CGPoint) point DidBlock :(DidBlock) didBlock{
//获取当前日期
NSDate *date = [NSDate date];
//调用刚刚封装的日历
return [self initWithPoint:point DidBlock:didBlock date:date];
}
附加:可选优化
给日历添加蒙版
//给外界定义一个属性contentView
@property (nonatomic,strong) UIView *contentView;
这里代码加进initXMPickDate里面
self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 328, 340)];
self.contentView.layer.cornerRadius = 20.0;
[self addSubview:self.contentView];
[self.contentView setBackgroundColor:[UIColor blackColor]];
[self.contentView setAlpha:0.16];