由于工作需求自己写了一个日历, 大概思路是: 通过collectionView来做, 具备上一月下一月的切换, 日历样式自定义collectionViewCell就可以.
关键代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
_currentDate = [NSDate date];
_firstDay = [self firstWeekdayInThisMotnth:_currentDate];
_totalDays = [self totaldaysInMonth:_currentDate];
[self.view addSubview:self.collectionView];
}
#pragma mark - 懒加载collectiongView
- (UICollectionView *)collectionView {
if (!_collectionView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 0;
layout.minimumInteritemSpacing = 0;
layout.itemSize = CGSizeMake(([UIScreen mainScreen].bounds.size.width -20) / 7, ([UIScreen mainScreen].bounds.size.width -20) / 7 * 1.6);
layout.headerReferenceSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 165);
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.contentInset = UIEdgeInsetsMake(0, 10, 0, 10);
[_collectionView registerNib:[UINib nibWithNibName:@"CalendarCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"CalendarCollectionViewCell"];
// 如果有头部视图必须要先注册
[_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerViewIdentifier];
_collectionView.alwaysBounceVertical = YES;
_collectionView.alwaysBounceHorizontal = NO;
}
return _collectionView;
}
#pragma mark - UICollectionViewDatasource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _totalDays + _firstDay;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
HMCalendarCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"HMCalendarCollectionViewCell" forIndexPath:indexPath];
NSInteger day = indexPath.item - _firstDay;
[cell setDataWithIndex:day + 1 withIndex:indexPath.item];
NSString *dayStr = @"";
if ((day + 1) > 9) {
dayStr = [NSString stringWithFormat:@"%zd",(day + 1)];
} else {
dayStr = [NSString stringWithFormat:@"0%zd",(day + 1)];
}
return cell;
}
#pragma mark - 日期的相关处理
// 上一月
- (void)lastMonthClick {
_currentDate = [self lastMonth:_currentDate];
_firstDay = [self firstWeekdayInThisMotnth:_currentDate];
_totalDays = [self totaldaysInMonth:_currentDate];
[self.collectionView reloadData];
}
// 下一月
- (void)nextMonthClick {
_currentDate = [self nextMonth:_currentDate];
_firstDay = [self firstWeekdayInThisMotnth:_currentDate];
_totalDays = [self totaldaysInMonth:_currentDate];
[self.collectionView reloadData];
}
// 计算某月的第一天为周几
- (NSInteger)firstWeekdayInThisMotnth:(NSDate *)date{
NSCalendar *calendar = [NSCalendar currentCalendar]; // 取得当前用户的逻辑日历(logical calendar)
[calendar setFirstWeekday:2]; // 设定每月的第一天从星期几开始,比如:. 如需设定从星期日开始,则value传入1 ,如需设定从星期一开始,则value传入2 ,以此类推
NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
[comp setDay:1]; // 设置为这个月的第一天
NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];
NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; // 这个月第一天在当前日历的顺序
// 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的顺序
return firstWeekday - 1;
}
// 计算某月一共有多少天
- (NSInteger)totaldaysInMonth:(NSDate *)date{
NSRange daysInOfMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的范围
return daysInOfMonth.length;
}
// 日历的上一个月
- (NSDate *)lastMonth:(NSDate *)date{
NSDateComponents *comp = [[NSDateComponents alloc]init];
comp.month = -1;
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:comp toDate:date options:0];
return newDate;
}
// 日历的下一个月
- (NSDate *)nextMonth:(NSDate *)date{
NSDateComponents *comp = [[NSDateComponents alloc]init];
comp.month = 1;
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:comp toDate:date options:0];
return newDate;
}
#pragma mark - 日期处理方法(附加)
// 处理日期的上一日下一日
- (void)processingDateWithType:(NSInteger)type {
// type 1为下一日 -1为上一日
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *adComps = [[NSDateComponents alloc] init];
[adComps setDay:type];
_currentDate = [calendar dateByAddingComponents:adComps toDate:_currentDate options:0];
self.dateLabel.text = [_currentDate stringWithDateFormatter:@"yyyy.MM.dd"];
}
// 判断是不是当天
- (BOOL)isSameDay:(NSDate*)date1 date2:(NSDate*)date2
{
NSCalendar* calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents* comp1 = [calendar components:unitFlags fromDate:date1];
NSDateComponents* comp2 = [calendar components:unitFlags fromDate:date2];
return [comp1 day] == [comp2 day] &&
[comp1 month] == [comp2 month] &&
[comp1 year] == [comp2 year];
}