(一)前言服务器
项目中须要签到功能,因此要运用到一个简易日历,原来老版本的日历用户体验至关的很差,因此在这里封装一个简易的日历,关键的点就是:当前月的第一天是星期几以及当前月有多少天,下面看代码。布局
(二)布局;测试
(1)整个view分两个部分,顶部为一个显示时间的topview,里面在添加一个uilabel显示时间;下部是一个UICollectionView,分为两个section,第一个section是显示星期几;第二个section显示的当前月份的days;ui
(2)view里面能够加入数据交互,好比从后台获取信息并显示;atom
#import "ZJCalendar.h" #import "ZJCalendarCell.h" static NSString * const ZJCalendarCellIdentifier = @"cell"; @interface ZJCalendar () { UILabel *_monthLabel; } @property (nonatomic,strong) UICollectionView *ZJCollectionView; @property (nonatomic,strong) NSDate *date; @property (nonatomic,assign) CGRect rect; @property (nonatomic,strong) NSArray *array; @property (nonatomic,strong) NSArray *weekDayArray; @property (nonatomic,strong) UIView *topDateView; @end @implementation ZJCalendar - (instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor whiteColor]; [self setTopView]; self.date = [NSDate date]; self.rect = CGRectMake(0, CGRectGetHeight(self.topDateView.frame), frame.size.width, frame.size.height-CGRectGetHeight(self.topDateView.frame)); [self setView:self.rect]; _weekDayArray = @[@"日",@"一",@"二",@"三",@"四",@"五",@"六"]; } return self; } - (void)drawRect:(CGRect)rect { [self addSwipe]; [self getServiceData]; } - (void)setDate:(NSDate *)date { _date = date; NSDateFormatter *f = [[NSDateFormatter alloc] init]; f.dateFormat = @"yyyy-MM-dd"; NSString *strDate = [f stringFromDate:self.date]; _monthLabel.text = strDate; [self.ZJCollectionView reloadData]; } - (void)setTopView{ self.topDateView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), 50)]; self.topDateView.backgroundColor = [UIColor lightGrayColor]; _monthLabel = [[UILabel alloc] initWithFrame:self.topDateView.bounds]; _monthLabel.textAlignment = NSTextAlignmentCenter; _monthLabel.textColor = [UIColor redColor]; _monthLabel.font = [UIFont systemFontOfSize:20]; [self.topDateView addSubview:_monthLabel]; [self addSubview:self.topDateView]; } - (void)setView:(CGRect)frame { CGFloat item_with = CGRectGetWidth(frame)/7; CGFloat item_height = CGRectGetWidth(frame)/7; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.itemSize = CGSizeMake(item_with, item_height); layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); layout.minimumInteritemSpacing = 0; layout.minimumLineSpacing = 0; self.ZJCollectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout]; self.ZJCollectionView.backgroundColor = [UIColor whiteColor]; [self.ZJCollectionView registerClass:[ZJCalendarCell class] forCellWithReuseIdentifier:ZJCalendarCellIdentifier]; self.ZJCollectionView.dataSource = self; self.ZJCollectionView.delegate = self; [self addSubview:self.ZJCollectionView]; } - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return 2; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ if (section==0) { return _weekDayArray.count; } return 42; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ ZJCalendarCell *cell = (ZJCalendarCell *)[collectionView dequeueReusableCellWithReuseIdentifier:ZJCalendarCellIdentifier forIndexPath:indexPath]; if (indexPath.section==0) { NSString *weekday = [_weekDayArray objectAtIndex:indexPath.row]; if (indexPath.row==0||indexPath.row==6) { cell.dateLabel.textColor = [UIColor colorWithRed:0 green:160.0f/255 blue:223.0f/255 alpha:1.0]; }else{ cell.dateLabel.textColor = [UIColor blackColor]; } cell.dateLabel.text = weekday; [cell hiddenRightLineView]; }else{ NSInteger firstWeekday = [self firstweekdayInThisMonth:self.date]; NSInteger daysInMonth = [self totaldayInThisMonth:self.date]; NSInteger daysInlastMonth = [self totaldayInThisMonth:[self lastMonth:self.date]]; NSInteger day = 0; NSInteger i = indexPath.row; [cell hiddenRightLineView]; if (i < firstWeekday) { cell.dateLabel.textColor = [UIColor lightGrayColor]; cell.dateLabel.text = [NSString stringWithFormat:@"%ld",(long)daysInlastMonth-firstWeekday+i+1]; }else if (i > firstWeekday+daysInMonth-1){ cell.dateLabel.textColor = [UIColor lightGrayColor]; cell.dateLabel.text = [NSString stringWithFormat:@"%ld",(long)i-firstWeekday-daysInMonth+1]; }else{ day = i-firstWeekday+1; cell.dateLabel.textColor = [UIColor blackColor]; NSString *key = [NSString stringWithFormat:@"%d",day]; if (self.array) { for (NSString *testString in self.array) { if ([testString isEqualToString:key]) { cell.dateLabel.textColor = [UIColor orangeColor]; break; } } } cell.dateLabel.text = [NSString stringWithFormat:@"%ld",(long)day]; } } return cell; } - (NSInteger)firstweekdayInThisMonth:(NSDate *)date{ NSCalendar *calendar = [NSCalendar currentCalendar]; calendar.firstWeekday = 1; NSDateComponents *com = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date]; com.day = 1; NSDate *firstDayOfMonthDate = [calendar dateFromComponents:com]; NSInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; return firstWeekday - 1; } - (NSInteger)totaldayInThisMonth:(NSDate *)date{ NSRange daysInMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; return daysInMonth.length; } - (NSDate *)lastMonth:(NSDate *)date{ NSDateComponents *com = [[NSDateComponents alloc] init]; com.month = -1; NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:com toDate:date options:0]; return newDate; } - (NSDate *)nextMonth:(NSDate *)date{ NSDateComponents *com = [[NSDateComponents alloc] init]; com.month = 1; NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:com toDate:date options:0]; return newDate; } - (void)left:(UIGestureRecognizer *)left{ [UIView transitionWithView:self duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.date = [self nextMonth:self.date]; } completion:^(BOOL finished) { if (finished) { [self getServiceData]; } }]; } - (void)right:(UIGestureRecognizer *)right{ [UIView transitionWithView:self duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.date = [self lastMonth:self.date]; } completion:^(BOOL finished) { if (finished) { [self getServiceData]; } }]; } - (void)addSwipe { UISwipeGestureRecognizer *swipLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(left:)]; swipLeft.direction = UISwipeGestureRecognizerDirectionLeft; [self addGestureRecognizer:swipLeft]; UISwipeGestureRecognizer *swipRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(right:)]; swipRight.direction = UISwipeGestureRecognizerDirectionRight; [self addGestureRecognizer:swipRight]; } - (void)getServiceData{ //能够请求服务器数据,这里为了测试,设置了固定的数据; self.array = @[@"13",@"18",@"1",@"14",@"4",@"22"]; [self.ZJCollectionView reloadData]; } @end
(3)关于自定义的cell,主要是一个label和两个分割线;用的是masonry自适应布局;code
#import "ZJCalendarCell.h" #import <Masonry.h> #define kScreenWidth CGRectGetWidth([UIScreen mainScreen].bounds) @interface ZJCalendarCell () { UIView *bottomLine; UIView *rightLine; } @end @implementation ZJCalendarCell - (instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor whiteColor]; self.dateLabel = [[UILabel alloc] init]; self.dateLabel.textAlignment = NSTextAlignmentCenter; [self.contentView addSubview:self.dateLabel]; __weak typeof(self) weakSelf = self; [self.dateLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(weakSelf.contentView); }]; bottomLine = [[UIView alloc] init]; bottomLine.backgroundColor = [UIColor lightGrayColor]; [self.contentView addSubview:bottomLine]; [bottomLine mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(self.contentView.mas_leading); make.trailing.equalTo(self.contentView.mas_trailing); make.height.mas_equalTo(0.5); make.bottom.equalTo(self.contentView.mas_bottom); }]; rightLine = [[UIView alloc] init]; rightLine.backgroundColor = [UIColor lightGrayColor]; [self.contentView addSubview:rightLine]; [rightLine mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.contentView.mas_top); make.trailing.equalTo(self.contentView.mas_trailing); make.width.mas_equalTo(0.5); make.bottom.equalTo(self.contentView.mas_bottom); }]; } return self; } - (void)hiddenRightLineView { if (self.frame.origin.x + self.frame.size.width >= kScreenWidth) { rightLine.hidden = YES; }else{ rightLine.hidden = NO; } } @end
(三)总结;component
这个只是简易的日历,功能比较单一;主要是为了知足当前项目的须要;第三方也有不少相关的控件,并且技术以及功能都比较丰富。orm