首先谈谈组成
整体是个CollectionView,每个月就是一个section,XXXX年XX月和周一到周日部分是每个分组的Header,每个分组其实有42个Item,如果是当月的Item显示号数和副标题,如果不是当月的Item显示空字符串并且隐藏当天的副标题
接下来是实现
第一步 创建CalendarDateModel继承自NSObject
#import <Foundation/Foundation.h>
@interface CalendarDateModel : NSObject
@property (nonatomic, copy)NSString *day;//当天的号数 如果非当月为空字符串
@property (nonatomic, assign)BOOL isPast;//用于在第一个月判断是否是过的天数
//可以根据需求添加需要的属性 这个model就是存储在Item上需要显示的信息
@end
第二步 创建CalendarDateManager 该类用于管理数据源 如果有网络请求可以加在这里
.h
#import <Foundation/Foundation.h>
#import "CalendarDateModel.h"
@interface CalendarDateManager : NSObject
- (NSArray *)getDateArray;
@end
.m
#import "CalendarDateManager.h"
@interface CalendarDateManager (){
NSMutableArray *_dateArray;
}
@property (nonatomic, strong)NSDateFormatter *formatter;
@end
@implementation CalendarDateManager
- (instancetype)init
{
self = [super init];
if (self) {
[self initDateArray];
}
return self;
}
- (NSArray *)getDateArray{
return _dateArray.copy;
}
- (void)initDateArray{
NSDate *date = [NSDate new];//获取当前时间
NSInteger toDay = [self day:date];//获取当天是几号
_dateArray = [NSMutableArray arrayWithCapacity:6];//这里写死了一次创建6个月 可以根据需要改变 或者可以写一个传创建几个月参数的初始化函数
for (int i = 0; i < 6; i++) { //循环6次 (6个月)
NSMutableArray *tmpArray = [NSMutableArray arrayWithCapacity:42];
NSInteger daysInThisMonth = [self totaldaysInThisMonth:date];
NSInteger firstWeekday = [self firstWeekdayInThisMonth:date];
for (NSInteger day = 0; day < 43; day++) {
CalendarDateModel *model = [CalendarDateModel new];
if (day < firstWeekday) {
model.day = @"";
}else if (day > firstWeekday + daysInThisMonth - 1){
model.day = @"";
}else{
if (i == 0) {//只判断第一个月的天数是否是过去 后面几个月没必要判断
if (day - firstWeekday + 1 < toDay) {
model.isPast = YES;
}//else不用判断 默认NO
}
model.day = [NSString stringWithFormat:@"%ld", day - firstWeekday + 1];
}
[tmpArray addObject:model];
}
NSDictionary *dic = @{@"date":[self.formatter stringFromDate:date], @"itemList":tmpArray};
[_dateArray addObject:dic];
date = [self nextMonth:date];
}
}
- (NSDateFormatter *)formatter{
if (!_formatter) {
_formatter = [[NSDateFormatter alloc] init];
_formatter.locale = [NSLocale localeWithLocaleIdentifier:@"zh_CN"];
[_formatter setDateFormat:@"yyyy-MM"];
}
return _formatter;
}
#pragma mark- 返回下个月的date
- (NSDate*)nextMonth:(NSDate *)date{
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.month = +1;
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:date options:0];
return newDate;
}
#pragma mark- 返回明天的date
- (NSDate*)nextDay:(NSDate *)date{
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.day = +1;
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:date options:0];
return newDate;
}
#pragma mark- 获取当前时间是几号
- (NSInteger)day:(NSDate *)date{
NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];
return [components day];
}
#pragma mark- 获取当月第一天的星期数
- (NSInteger)firstWeekdayInThisMonth:(NSDate *)date{
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setFirstWeekday:1];//1.Sun. 2.Mon. 3.Thes. 4.Wed. 5.Thur. 6.Fri. 7.Sat.
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];
return firstWeekday - 1;
}
#pragma mark- 获取当月天数
- (NSInteger)totaldaysInThisMonth:(NSDate *)date{
NSRange totaldaysInMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];
return totaldaysInMonth.length;
}
@end
第三步 自定义CollectionViewCell 和UICollectionReusableView
CalendarDateItem.h
#import <UIKit/UIKit.h>
@class CalendarDateModel;
@interface CalendarDateItem : UICollectionViewCell
- (void)setModel:(CalendarDateModel *)model;
@end
.m
#import "CalendarDateItem.h"
#import "CalendarDateModel.h"
#define COLOFOR0X(c) [UIColor colorWithRed:((c>>16)&0xFF)/255.0 \
green:((c>>8)&0xFF)/255.0 \
blue:(c&0xFF)/255.0 \
alpha:1.0]
#define COLORMAINBLUE COLOFOR0X(0x00b7f3)
@interface CalendarDateItem ()
@property (weak, nonatomic) IBOutlet UILabel *dayLabel;
@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
@end
@implementation CalendarDateItem
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setModel:(CalendarDateModel *)model{
_dayLabel.text = model.day;
if ([_dayLabel.text isEqualToString:@""]) {
_priceLabel.hidden = YES;
}else{
if (model.isPast) {
_dayLabel.textColor = COLOFOR0X(0xbfbfbf);
_priceLabel.hidden = YES;
}else{
_dayLabel.textColor = COLORMAINBLUE;
_priceLabel.hidden = NO;
}
}
}
@end
CalendarMonthHeaderView.h
#import <UIKit/UIKit.h>
@interface CalendarMonthHeaderView : UICollectionReusableView
- (void)setDateString:(NSString *)date;
@end
.m
#import "CalendarMonthHeaderView.h"
@interface CalendarMonthHeaderView ()
@property (weak, nonatomic) IBOutlet UILabel *dateLabel;
@end
@implementation CalendarMonthHeaderView
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setDateString:(NSString *)date{
NSArray *array = [date componentsSeparatedByString:@"-"];
_dateLabel.text = [NSString stringWithFormat:@"%@ 年 %@ 月", array[0], array[1]];
}
@end
第四步 实现效果
#import "CalendarController.h"
#import "CalendarDateItem.h"
#import "CalendarMonthHeaderView.h"
#import "CalendarDateManager.h"
#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
@interface CalendarController ()<UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
@property (weak, nonatomic) IBOutlet UICollectionView *selectLiveTimeCollectionView;
@property (nonatomic, copy) NSArray *dateDataArray;
@end
@implementation CalendarController
- (void)viewDidLoad {
[super viewDidLoad];
UINib *nib = [UINib nibWithNibName:@"CalendarDateItem" bundle:nil];
[_selectLiveTimeCollectionView registerNib:nib forCellWithReuseIdentifier:@"CalendarDateItem"];
[_selectLiveTimeCollectionView registerNib:[UINib nibWithNibName:@"CalendarMonthHeaderView" bundle:nil]
forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CalendarMonthHeaderView"];
}
- (NSArray *)dateDataArray{
if (!_dateDataArray) {
_dateDataArray = [[[CalendarDateManager alloc] init] getDateArray];
}
return _dateDataArray;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return self.dateDataArray.count;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 42;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CalendarDateItem *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CalendarDateItem" forIndexPath:indexPath];
NSDictionary *dic = _dateDataArray[indexPath.section];
NSArray *tmpArray = dic[@"itemList"];
[cell setModel:tmpArray[indexPath.row]];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake(SCREEN_WIDTH / 7.0, 45);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 0;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if (kind == UICollectionElementKindSectionHeader) {
CalendarMonthHeaderView *headerRV = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"CalendarMonthHeaderView" forIndexPath:indexPath];
NSDictionary *dic = _dateDataArray[indexPath.section];
[headerRV setDateString:dic[@"date"]];
return headerRV;
}else{
return nil;
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
return CGSizeMake(SCREEN_WIDTH, 111);
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{
return CGSizeMake(0, 0);
}
@end