由于工作需求自己寫(xiě)了一個(gè)日歷, 大概思路是: 通過(guò)collectionView來(lái)做, 具備上一月下一月的切換, 日歷樣式自定義collectionViewCell就可以.
關(guān)鍵代碼如下:
- (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"];
// 如果有頭部視圖必須要先注冊(cè)
[_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 - 日期的相關(guān)處理
// 上一月
- (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];
}
// 計(jì)算某月的第一天為周幾
- (NSInteger)firstWeekdayInThisMotnth:(NSDate *)date{
NSCalendar *calendar = [NSCalendar currentCalendar]; // 取得當(dāng)前用戶(hù)的邏輯日歷(logical calendar)
[calendar setFirstWeekday:2]; // 設(shè)定每月的第一天從星期幾開(kāi)始轿衔,比如:. 如需設(shè)定從星期日開(kāi)始,則value傳入1 闹伪,如需設(shè)定從星期一開(kāi)始,則value傳入2 掀宋,以此類(lèi)推
NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
[comp setDay:1]; // 設(shè)置為這個(gè)月的第一天
NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];
NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; // 這個(gè)月第一天在當(dāng)前日歷的順序
// 返回某個(gè)特定時(shí)間(date)其對(duì)應(yīng)的小的時(shí)間單元(smaller)在大的時(shí)間單元(larger)中的順序
return firstWeekday - 1;
}
// 計(jì)算某月一共有多少天
- (NSInteger)totaldaysInMonth:(NSDate *)date{
NSRange daysInOfMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; // 返回某個(gè)特定時(shí)間(date)其對(duì)應(yīng)的小的時(shí)間單元(smaller)在大的時(shí)間單元(larger)中的范圍
return daysInOfMonth.length;
}
// 日歷的上一個(gè)月
- (NSDate *)lastMonth:(NSDate *)date{
NSDateComponents *comp = [[NSDateComponents alloc]init];
comp.month = -1;
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:comp toDate:date options:0];
return newDate;
}
// 日歷的下一個(gè)月
- (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"];
}
// 判斷是不是當(dāng)天
- (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];
}