You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
10 KiB
280 lines
10 KiB
// |
|
// EBCalendarView.m |
|
// EBCalendarViewDemo |
|
// |
|
// Created by HoYo on 2018/4/25. |
|
// Copyright © 2018年 HoYo. All rights reserved. |
|
// |
|
|
|
#import "EBCalendarView.h" |
|
#import "EBCalendarDayCell.h" |
|
#import "EBCalenderWeekView.h" |
|
#import "EBCalenderNavigationView.h" |
|
#import "NSDate+EBAdd.h" |
|
#import "UIColor+EBAdd.h" |
|
|
|
@interface EBCalendarView()<UICollectionViewDataSource, UICollectionViewDelegate, EBCalenderNavigationViewDelegate> |
|
@property (nonatomic, strong) UICollectionView *collectionView; |
|
@property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout; |
|
@property (nonatomic, strong) EBCalenderWeekView *weekView; |
|
@property (nonatomic, strong) EBCalenderNavigationView *navigationView; |
|
@property (nonatomic, strong) NSMutableArray *dates; |
|
@property (nonatomic, assign) NSInteger currentYear, currentMonth; |
|
@property (nonatomic, strong) NSDate *selectedDate; |
|
@end |
|
|
|
static NSString *const kEBCalendarViewReuseIdentifier = @"EBCalendarDayCell"; |
|
// 周视图高度 |
|
static CGFloat const kEBCalendarViewWeekViewHeight = 45; |
|
// 左右导航视图高度 |
|
static CGFloat const kEBCalenderNavigationViewHeight = 50; |
|
// Cell高度 |
|
static CGFloat const kEBCalendarViewCellHeight = 35; |
|
// 列数 |
|
static CGFloat const kEBCalendarViewCellColumn = 7.0; |
|
@implementation EBCalendarView |
|
|
|
#pragma mark - Init |
|
- (instancetype)initWithFrame:(CGRect)frame { |
|
self = [super initWithFrame:frame]; |
|
if (self) { |
|
[self setupView]; |
|
[self dataBuilder]; |
|
} |
|
return self; |
|
} |
|
|
|
- (void)layoutSubviews { |
|
[super layoutSubviews]; |
|
[self setupFrame]; |
|
} |
|
#pragma mark - Setup |
|
- (void)setupView { |
|
[self addSubview:self.navigationView]; |
|
[self addSubview:self.weekView]; |
|
[self addSubview:self.collectionView]; |
|
|
|
|
|
UISwipeGestureRecognizer *leftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; |
|
leftGesture.direction = UISwipeGestureRecognizerDirectionLeft; |
|
[_collectionView addGestureRecognizer:leftGesture]; |
|
|
|
UISwipeGestureRecognizer *rightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; |
|
rightGesture.direction = UISwipeGestureRecognizerDirectionRight; |
|
[_collectionView addGestureRecognizer:rightGesture]; |
|
} |
|
|
|
- (void)setupFrame |
|
{ |
|
CGFloat viewWidth = CGRectGetWidth(self.bounds); |
|
_navigationView.frame = CGRectMake(0, 0, viewWidth, kEBCalenderNavigationViewHeight); |
|
_weekView.frame = CGRectMake(0, CGRectGetMaxY(_navigationView.frame), viewWidth, kEBCalendarViewWeekViewHeight); |
|
_collectionView.frame = CGRectMake(0, CGRectGetMaxY(_weekView.frame), viewWidth, 235); |
|
_flowLayout.itemSize = CGSizeMake(viewWidth / kEBCalendarViewCellColumn, kEBCalendarViewCellHeight); |
|
//[UICommon ui_uiViewFillet:_collectionView.frame Viewdirection:PYUIdirectionBotton toView:_collectionView sizeMake:16]; |
|
} |
|
|
|
#pragma mark - Private |
|
- (void)handleSwipeGesture:(UISwipeGestureRecognizer *)recognizer { |
|
if(recognizer.direction==UISwipeGestureRecognizerDirectionLeft) { |
|
// 上个月 |
|
[self calenderNavigationViewDidChangeMonth:_navigationView isNextMonth:YES]; |
|
} |
|
if (recognizer.direction == UISwipeGestureRecognizerDirectionRight) { |
|
// 下个月 |
|
[self calenderNavigationViewDidChangeMonth:_navigationView isNextMonth:NO]; |
|
} |
|
} |
|
|
|
- (void)dataBuilder { |
|
_maxLastMonths = -1; |
|
_maxNextMonths = 0; |
|
[self createMonthData:[NSDate date]]; |
|
// 周数据 |
|
_weekView.weeks = @[@"一", @"二", @"三", @"四", @"五", @"六", @"日"]; |
|
} |
|
|
|
- (void)createMonthData:(NSDate*)date { |
|
_currentYear = date.year; |
|
_currentMonth = date.month; |
|
_navigationView.showDate = [date stringWithFormat:@"yyyy年MM月"]; |
|
_dates = [NSMutableArray new]; |
|
// 当前月第一天 |
|
NSDate *firstDayOfMonth = [NSDate dateWithString:[NSString stringWithFormat:@"%zd-%zd-01" |
|
, _currentYear |
|
, _currentMonth] format:@"yyyy-MM-dd"]; |
|
// 当前月的总天数 |
|
NSUInteger days = firstDayOfMonth.numberOfDaysInMonth; |
|
// 当前月第一天周几,1是周日 |
|
NSInteger weekday = firstDayOfMonth.weekday - 1; |
|
// -1之后周日会变成0 |
|
if (weekday == 0) { |
|
weekday = 7; |
|
} |
|
// 填充上月的空数据 |
|
for (int n = 1; n < weekday; n++) { |
|
EBCalendarModel *model = [EBCalendarModel new]; |
|
[_dates addObject:model]; |
|
} |
|
// 填充本月的日期 |
|
for (int n = 1; n <= days; n ++) { |
|
EBCalendarModel *model = [EBCalendarModel new]; |
|
model.year = _currentYear; |
|
model.month = _currentMonth; |
|
model.day = n; |
|
if ([model.date isToday]) { |
|
model.today = YES; |
|
} |
|
[_dates addObject:model]; |
|
} |
|
//_dates = [datasource copy]; |
|
|
|
// 小数向上取整 |
|
NSInteger rows = ceilf(_dates.count / kEBCalendarViewCellColumn); |
|
self.frame = ({ |
|
CGRect frame = self.frame; |
|
frame.size.height = kEBCalendarViewWeekViewHeight + kEBCalenderNavigationViewHeight + (rows * kEBCalendarViewCellHeight); |
|
frame; |
|
}); |
|
[self signViewUpdate]; |
|
} |
|
|
|
|
|
#pragma mark - UICollectionViewDataSource and UICollectionViewDelegate |
|
|
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { |
|
return _dates.count; |
|
} |
|
|
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath |
|
{ |
|
EBCalendarDayCell *cell = (EBCalendarDayCell*)[collectionView dequeueReusableCellWithReuseIdentifier:kEBCalendarViewReuseIdentifier forIndexPath:indexPath]; |
|
EBCalendarModel *model = _dates[indexPath.row]; |
|
// 月份切换时回显之前选中的日期状态 |
|
if (_selectedDate && [model.date isEqual:_selectedDate]) |
|
{ |
|
model.selected = YES; |
|
} |
|
[cell configWithCalendarModel:model]; |
|
return cell; |
|
} |
|
|
|
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath |
|
{ |
|
EBCalendarModel *model = _dates[indexPath.row]; |
|
NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; |
|
[formatter setDateFormat:@"dd"]; |
|
NSString *dayString = [formatter stringFromDate:[NSDate date]]; |
|
[formatter setDateFormat:@"MM"]; |
|
NSString *monthString = [formatter stringFromDate:[NSDate date]]; |
|
if (model.month == monthString.intValue && model.day != dayString.intValue )/// 如果选择时间大于当天,直接return |
|
return; |
|
|
|
if (model.isSelected) return; |
|
model.selected = YES; |
|
// 上月的数据显示为空,并且不能点击 |
|
if(model.year == 0) return; |
|
|
|
for (int i = 0; i < _dates.count; i++) |
|
{ |
|
EBCalendarModel *models = _dates[i]; |
|
if(models.year == model.year && model.month == models.month && models.day == model.year) |
|
{ |
|
[_dates replaceObjectAtIndex:i withObject:model]; |
|
break; |
|
} |
|
} |
|
[collectionView reloadData]; |
|
_selectedDate = model.date; |
|
if ([self.delegate respondsToSelector:@selector(calendarView:didSelectedDate:)]) { |
|
[self.delegate calendarView:self didSelectedDate:model.date]; |
|
} |
|
} |
|
|
|
- (void)signViewUpdate |
|
{ |
|
for (int i = 0; i < _dates.count; i++) |
|
{ |
|
EBCalendarModel *model = _dates[i]; |
|
NSString *time = [NSString stringWithFormat:@"%ld-%ld-%ld",model.year,model.month,model.day]; |
|
for (NSString *singTime in self.signDate) |
|
{ |
|
if ([singTime isEqualToString:time]) |
|
{ |
|
model.selected = YES; |
|
[_dates replaceObjectAtIndex:i withObject:model]; |
|
} |
|
} |
|
} |
|
[_collectionView reloadData]; |
|
} |
|
|
|
#pragma mark - EBCalenderNavigationViewDelegate |
|
- (void)calenderNavigationViewDidChangeMonth:(EBCalenderNavigationView *)calenderNavigationView isNextMonth:(BOOL)isNextMonth |
|
{ |
|
NSInteger addMonths = 1; |
|
if (!isNextMonth) { |
|
addMonths = -1; |
|
} |
|
NSDate *date = [[NSDate dateWithString:[NSString stringWithFormat:@"%zd-%zd-01" |
|
, _currentYear |
|
, _currentMonth] format:@"yyyy-MM-dd"] dateByAddingMonths:addMonths]; |
|
if (_maxLastMonths >= 0) { |
|
NSDate *maxLastMonthDate = [[NSDate dateWithString:[NSString stringWithFormat:@"%zd-%zd-01" |
|
, [NSDate date].year |
|
, [NSDate date].month] format:@"yyyy-MM-dd"] dateByAddingMonths:-_maxLastMonths]; |
|
if ([maxLastMonthDate compare:date] > 0 ) return; |
|
} |
|
|
|
if (_maxNextMonths >= 0) { |
|
NSDate *maxNextMonthDate = [[NSDate dateWithString:[NSString stringWithFormat:@"%zd-%zd-01" |
|
, [NSDate date].year |
|
, [NSDate date].month] format:@"yyyy-MM-dd"] dateByAddingMonths:_maxNextMonths]; |
|
if ([maxNextMonthDate compare:date] < 0 ) return; |
|
} |
|
|
|
[self createMonthData:date]; |
|
} |
|
|
|
|
|
#pragma mark - Getter |
|
- (UICollectionViewFlowLayout*)flowLayout { |
|
if (!_flowLayout) { |
|
_flowLayout = [UICollectionViewFlowLayout new]; |
|
_flowLayout.minimumInteritemSpacing = 0;//cell 左右间距 |
|
_flowLayout.minimumLineSpacing = 0;//cell 上下间距 |
|
} |
|
return _flowLayout; |
|
} |
|
|
|
- (UICollectionView *)collectionView { |
|
if (!_collectionView) { |
|
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.flowLayout]; |
|
_collectionView.dataSource = self; |
|
_collectionView.delegate = self; |
|
_collectionView.showsVerticalScrollIndicator = NO; |
|
_collectionView.showsHorizontalScrollIndicator = NO; |
|
_collectionView.backgroundColor = [UIColor whiteColor]; |
|
[_collectionView registerClass:[EBCalendarDayCell class] forCellWithReuseIdentifier:kEBCalendarViewReuseIdentifier]; |
|
} |
|
return _collectionView; |
|
} |
|
|
|
- (EBCalenderNavigationView*)navigationView { |
|
if (!_navigationView) { |
|
_navigationView = [EBCalenderNavigationView new]; |
|
_navigationView.delegate = self; |
|
} |
|
return _navigationView; |
|
} |
|
|
|
- (EBCalenderWeekView*)weekView { |
|
if (!_weekView) { |
|
_weekView = [EBCalenderWeekView new]; |
|
_weekView.backgroundColor = UIColor.whiteColor; |
|
} |
|
return _weekView; |
|
} |
|
|
|
|
|
@end
|
|
|