NSCalendar 是 iOS 获取日历数据的工具类。
获取指定月份的天数:
// 获取当月的天数
NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:[NSDate date]];
// 天数
self.daysOfMouth = range.length;
获取指定日期的是周几,在 NSCalendar
中,默认周日为每周的第一天,序号为 1
,周一为 2
,以此类推:
// 获取今天是周几
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comps = [calendar components:NSCalendarUnitWeekday fromDate:[NSDate date]];
// 默认周日为每周的第一天,序号为1,周一为2,以此类推
NSInteger firstDay = [comps weekday];
根据产品需求,设计如下的月份 UI
:
使用 UICollectionView
来展示月份。
声明全局变量:
/**
当前月份
*/
@property (weak, nonatomic) UILabel *labCurrentMouth;
/**
日历网格
*/
@property (weak, nonatomic) UICollectionView *collectCalendar;
/**
本月有多少天
*/
@property (assign, nonatomic) NSInteger daysOfMouth;
/**
每个月第一行空白的天数
*/
@property (assign, nonatomic) NSInteger numBlank;
UICollectionView
布局:
// 月份日历
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];
flowLayout.sectionInset = UIEdgeInsetsMake(0, 7.5, 0, 7.5);
flowLayout.minimumLineSpacing = 2;
flowLayout.minimumInteritemSpacing = 15;
flowLayout.itemSize = CGSizeMake(25, 25);
UICollectionView *collectTemp = [[UICollectionView alloc] initWithFrame:CGRectMake(widthEdge, 82, 294, 168) collectionViewLayout:flowLayout];
[collectTemp setBackgroundColor:kColor_C6];
collectTemp.delegate = self;
collectTemp.dataSource = self;
[checkInView addSubview:collectTemp];
self.collectCalendar = collectTemp;
// 注册 cell
[self.collectCalendar registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:gDayID];
因为星期的排版是固定的,所以月份需要根据第一天是周几来空出相应的空白天数,以便和星期相对应。
月份布局的相关计算:
// 当月时间戳
NSDate * currentDate = [NSDate date];
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-M"];
NSString *strCurrent = [formatter stringFromDate:currentDate];
[self.labCurrentMouth setText:[strCurrent stringByAppendingFormat:@"月"]];
// 计算月份的第一天为周几
// 获取每月的第一天
NSString * strFistDay = [NSString stringWithFormat:@"%@-1", strCurrent];
[formatter setDateFormat:@"yyyy-M-dd"];
NSDate *date = [formatter dateFromString:strFistDay];
// 日历中,默认周日一天,序号为1,周一为2,以此类推
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comps = [calendar components:NSCalendarUnitWeekday fromDate:date];
NSInteger firstDay = [comps weekday];
// 因为产品设计周一为第一天,所以要做相应的调整
// 每个月第一行空白的天数
if (firstDay == 1) {
// 第一天是周日
self.numBlank = 6;
} else {
self.numBlank = firstDay - 2;
}
// 获取当月的天数
NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:currentDate];
self.daysOfMouth = range.length;
UICollectionViewDelegate
和 UICollectionViewDataSource
:
#pragma mark - UICollectionDataSource
// 单元数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
// 月份排版的空白加上月份的总天数
return self.numBlank + self.daysOfMouth;
}
// cell 定义
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:gDayID forIndexPath:indexPath];
// 月份的号数
UILabel *labDay = (UILabel *)[cell viewWithTag:10];
if (labDay == nil) {
labDay = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[labDay setTag:10];
[labDay setClipsToBounds:YES];
[labDay.layer setCornerRadius:labDay.frame.size.height/2];
[labDay setTextAlignment:NSTextAlignmentCenter];
[cell addSubview:labDay];
[labDay setBackgroundColor:kColor_C1];
[labDay setFont:kFont_h3];
[labDay setTextColor:kColor_C6];
}
// 隐藏空白、显示号数
if (indexPath.row < self.numBlank) {
[labDay setHidden:YES];
} else {
[labDay setHidden:NO];
[labDay setText:[NSString stringWithFormat:@"%ld", (long)indexPath.row - self.numBlank + 1]];
}
return cell;
}
完成!