场景
最近公司App的UI 页面更新,出现了一个项目倒计时面板。该倒计时是用于计时项目到开放还剩余多少时间。效果如下:
分析上图
上图粉红色我标记的地方是倒计时的面板样式,我们把该样式看成10块元素组成。这10块元素如下:“距离项目上线还有:”、“0”、“9”、“小时”、“3”、“0”、“分”、“1”、“1”、“秒”。至于为什么要把时、分、秒的十位和个位分开,你看面板样式你就应该理解了。
使用到的的知识点
- 计算动态计算UILable 的宽度。
- 给UILable描边和切角。
- 定时器的使用(开始&暂停)。
- 定时器在默认的RunLoop中,当页面有滑动定时器不计时。
- 时间的进制转化。
- 求余数的知识。
- 时间戳的转换知识。
倒计时面板类
1、初始化10个元素。
-(instancetype)initWithFrame:(CGRect)frame{ if (self == [super initWithFrame:frame]) { // 初始化 lable1 = [UILabel new]; lable1.textAlignment = NSTextAlignmentCenter ; lable1.textColor = [UIColor colorWithDisplayP3Red:113/255.0 green:113/255.0 blue:113/255.0 alpha:1.0]; [self addSubview:lable1]; hoursTenLable = [UILabel new]; hoursTenLable.textAlignment = NSTextAlignmentCenter ; hoursTenLable.font = [UIFont systemFontOfSize:15]; [self addSubview:hoursTenLable]; hoursBitsLable = [UILabel new]; hoursBitsLable.textAlignment = NSTextAlignmentCenter ; hoursBitsLable.font = [UIFont systemFontOfSize:15]; [self addSubview:hoursBitsLable]; lable2 = [UILabel new]; lable2.textAlignment = NSTextAlignmentCenter ; lable2.textColor = [UIColor colorWithDisplayP3Red:113/255.0 green:113/255.0 blue:113/255.0 alpha:1.0]; [self addSubview:lable2]; minutesTenLable = [UILabel new]; minutesTenLable.textAlignment = NSTextAlignmentCenter ; minutesTenLable.font = [UIFont systemFontOfSize:15]; [self addSubview:minutesTenLable]; minutesBitsLable = [UILabel new]; minutesBitsLable.textAlignment = NSTextAlignmentCenter ; minutesBitsLable.font = [UIFont systemFontOfSize:15]; [self addSubview:minutesBitsLable]; lable3 = [UILabel new]; lable3.textAlignment = NSTextAlignmentCenter ; lable3.textColor = [UIColor colorWithDisplayP3Red:113/255.0 green:113/255.0 blue:113/255.0 alpha:1.0]; [self addSubview:lable3]; secondsTenLable = [UILabel new]; secondsTenLable.textAlignment = NSTextAlignmentCenter ; secondsTenLable.font = [UIFont systemFontOfSize:15]; [self addSubview:secondsTenLable]; secondsBitsLable = [UILabel new]; secondsBitsLable.textAlignment = NSTextAlignmentCenter ; secondsBitsLable.font = [UIFont systemFontOfSize:15]; [self addSubview:secondsBitsLable]; lable4 = [UILabel new]; lable4.textAlignment = NSTextAlignmentCenter ; lable4.textColor = [UIColor colorWithDisplayP3Red:113/255.0 green:113/255.0 blue:113/255.0 alpha:1.0]; [self addSubview:lable4]; } return self; }
#pragma mark 布局 -(void)layoutSubviews{ // 文字一 CGFloat lable1Wide = [self calculateLableWide:lable1]; lable1.frame = CGRectMake(0, 0, lable1Wide, Height); // 小时十位 CGFloat hoursWide = [self calculateLableWide:hoursTenLable]; hoursTenLable.layer.borderColor = [UIColor lightGrayColor].CGColor; hoursTenLable.layer.borderWidth = 0.5 ; hoursTenLable.layer.cornerRadius = cornerRadius ; hoursTenLable.frame = CGRectMake(CGRectGetMaxX(lable1.frame), 0, hoursWide+deviation, (hoursWide+deviation)*4/3); hoursTenLable.center = CGPointMake(hoursTenLable.center.x, lable1.center.y); // 小时个位 CGFloat hoursBits = [self calculateLableWide:hoursBitsLable]; hoursBitsLable.layer.borderColor = [UIColor lightGrayColor].CGColor; hoursBitsLable.layer.borderWidth = 0.5 ; hoursBitsLable.layer.cornerRadius = cornerRadius ; hoursBitsLable.frame = CGRectMake(CGRectGetMaxX(hoursTenLable.frame)+ TenMinDeviation, 0, hoursBits + deviation, (hoursBits+deviation)*4/3); hoursBitsLable.center = CGPointMake(hoursBitsLable.center.x, lable1.center.y); // 文字二 CGFloat lable2Wide = [self calculateLableWide:lable2]; lable2.frame = CGRectMake(CGRectGetMaxX(hoursBitsLable.frame), 0, lable2Wide, Height); // 分十位 CGFloat minutesWide = [self calculateLableWide:minutesTenLable]; minutesTenLable.layer.borderColor = [UIColor lightGrayColor].CGColor; minutesTenLable.layer.borderWidth = 0.5 ; minutesTenLable.layer.cornerRadius = cornerRadius ; minutesTenLable.frame = CGRectMake(CGRectGetMaxX(lable2.frame), 0, minutesWide + deviation, (minutesWide+deviation)*4/3); minutesTenLable.center = CGPointMake(minutesTenLable.center.x, lable1.center.y); // 分个位 CGFloat minutesBits = [self calculateLableWide:minutesBitsLable]; minutesBitsLable.layer.borderColor = [UIColor lightGrayColor].CGColor; minutesBitsLable.layer.borderWidth = 0.5 ; minutesBitsLable.layer.cornerRadius = cornerRadius ; minutesBitsLable.frame = CGRectMake(CGRectGetMaxX(minutesTenLable.frame)+ TenMinDeviation, 0, minutesBits + deviation, (minutesBits+deviation)*4/3); minutesBitsLable.center = CGPointMake(minutesBitsLable.center.x, lable1.center.y); // 文字三 CGFloat lable3Wide = [self calculateLableWide:lable3]; lable3.frame = CGRectMake(CGRectGetMaxX(minutesBitsLable.frame), 0, lable3Wide, Height); // 秒十位 CGFloat secondsWide = [self calculateLableWide:secondsTenLable]; secondsTenLable.layer.borderColor = [UIColor lightGrayColor].CGColor; secondsTenLable.layer.borderWidth = 0.5 ; secondsTenLable.layer.cornerRadius = cornerRadius ; secondsTenLable.frame = CGRectMake(CGRectGetMaxX(lable3.frame), 0, secondsWide + deviation, (secondsWide+deviation)*4/3); secondsTenLable.center = CGPointMake(secondsTenLable.center.x, lable1.center.y); // 秒个位 CGFloat secondsBits = [self calculateLableWide:secondsBitsLable]; secondsBitsLable.layer.borderColor = [UIColor lightGrayColor].CGColor; secondsBitsLable.layer.borderWidth = 0.5 ; secondsBitsLable.layer.cornerRadius = cornerRadius ; secondsBitsLable.frame = CGRectMake(CGRectGetMaxX(secondsTenLable.frame)+ TenMinDeviation, 0, secondsBits + deviation, (secondsBits+deviation)*4/3); secondsBitsLable.center = CGPointMake(secondsBitsLable.center.x, lable1.center.y); // 文字四 CGFloat lable4Wide = [self calculateLableWide:lable4]; lable4.frame = CGRectMake(CGRectGetMaxX(secondsBitsLable.frame), 0, lable4Wide, Height); self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, CGRectGetMaxX(lable4.frame), self.bounds.size.height); }
3、 当面版添加到分类View上的时候的处理。
-(void)willMoveToSuperview:(UIView *)newSuperview{
hoursTenValue = hoursTenLable.text.intValue;
hoursBitsValue = hoursBitsLable.text.intValue;
minutesBitsValue = minutesBitsLable.text.intValue;
minutesTenValue = minutesTenLable.text.intValue;
secondsTenValue = secondsTenLable.text.intValue;
secondsBitsValue = secondsBitsLable.text.intValue;
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countDownMethod) userInfo:nil repeats:YES];
// 解决由于滑动造成定时器不计时的问题
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
4、定时器时间的处理。
#pragma mark 时间处理事件
-(void)countDownMethod{
// 判断是否结束
if (hoursTenValue == 0 && hoursBitsValue==0 && minutesTenValue == 0 && minutesBitsValue == 0 && secondsTenValue == 0 && secondsBitsValue == 0) {
//[timer invalidate];
}
if (hoursBitsValue==0 && minutesTenValue ==0 && minutesBitsValue == 0 && secondsTenValue == 0 && secondsBitsValue == 0) {
hoursTenValue -- ;
hoursBitsValue = 9 ;
minutesTenValue = 5 ;
minutesBitsValue = 9 ;
secondsTenValue = 5 ;
secondsBitsValue = 10 ;
}
if(minutesTenValue ==0 && minutesBitsValue == 0 && secondsTenValue == 0 && secondsBitsValue == 0){
hoursBitsValue -- ;
minutesTenValue = 5 ;
minutesBitsValue = 9 ;
secondsTenValue = 5 ;
secondsBitsValue = 10 ;
}
if (minutesBitsValue == 0 && secondsTenValue == 0 && secondsBitsValue == 0) {
minutesTenValue--;
minutesBitsValue = 9 ;
secondsTenValue = 5 ;
secondsBitsValue = 10 ;
}
if (secondsTenValue == 0 && secondsBitsValue == 0) {
minutesBitsValue -- ;
secondsTenValue = 5 ;
secondsBitsValue = 10 ;
}
if (secondsBitsValue == 0) {
secondsTenValue--;
secondsBitsValue = 10 ;
}
if (secondsBitsValue != 0) {
secondsBitsValue -- ;
}
hoursTenLable.text = [NSString stringWithFormat:@"%ld",(long)hoursTenValue];
hoursBitsLable.text = [NSString stringWithFormat:@"%ld",(long)hoursBitsValue];
secondsTenLable.text = [NSString stringWithFormat:@"%ld",(long)secondsTenValue];
secondsBitsLable.text = [NSString stringWithFormat:@"%ld",(long)secondsBitsValue];
minutesTenLable.text = [NSString stringWithFormat:@"%ld",(long)minutesTenValue];
minutesBitsLable.text = [NSString stringWithFormat:@"%ld",(long)minutesBitsValue];
}
5、计算UILable的宽度
#pragma mark 计算文字的宽 -(CGFloat)calculateLableWide:(UILabel*)lable{ CGRect rect = [lable.text boundingRectWithSize:CGSizeMake(self.bounds.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes: @{NSFontAttributeName:lable.font,NSForegroundColorAttributeName:lable.textColor} context:nil]; return rect.size.width ; }
6、时间戳差转化成时分秒
// 计算两个时间的差值
-(NSArray*)getHMS:(NSString*)timeString1 withTimeStamp:(NSString*)timeString2 timeDateFormat:(NSString*)dateFormat{
// 判断两个值是否存在
if (timeString1==nil && timeString2==nil) {
return nil;
}
// 设置时间转化的格式
NSDateFormatter * formatter = [[NSDateFormatter alloc]init];
if (dateFormat==nil) {
dateFormat = @"YYYY-MM-dd HH:mm:ss";
}
[formatter setDateFormat:dateFormat];
// 将字符串转化成时间的数据
NSDate * date1 = [formatter dateFromString:timeString1];
NSDate * date2 = [formatter dateFromString:timeString2];
// 再将时间数据转化成时间戳
NSTimeInterval timeStamp1 = [date1 timeIntervalSince1970];
NSTimeInterval timeStamp2 = [date2 timeIntervalSince1970];
// 再计算两个时间的差值
NSTimeInterval timeStampdiff = ABS(timeStamp2 - timeStamp1);
// 时、分、秒的参数
int hours = 0 ,minutes = 0 , second = 0 ,day = 0;
// 计算各个的取值
second = (int)timeStampdiff % 60 ;
minutes = (int)timeStampdiff / 60 % 60;
hours = (int)timeStampdiff / 3600;
day = (int)timeStampdiff / (24 * 3600);
NSMutableArray * mutableArray = [NSMutableArray array];
// 计算结果的输出
hours = hours + day * 24 ;
if (hours>=10) {
[mutableArray addObject:@(hours/10)];
[mutableArray addObject:@(hours%10)];
}
[mutableArray addObject:@(0)];
[mutableArray addObject:@(hours%10)];
if (minutes>=10) {
[mutableArray addObject:@(minutes/10)];
[mutableArray addObject:@(minutes%10)];
}
[mutableArray addObject:@(0)];
[mutableArray addObject:@(minutes%10)];
if (second>=10) {
[mutableArray addObject:@(second/10)];
[mutableArray addObject:@(second%10)];
}
[mutableArray addObject:@(0)];
[mutableArray addObject:@(second%10)];
// 返回输出结果
return mutableArray ;
}
倒计时面板类的使用
// 设置
CountdownView * downView = [[CountdownView alloc]initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 40)];
downView->lable1.text = @"距离项目上线还有:";
downView->hoursTenLable.text = @"2";
downView->hoursBitsLable.text = @"3";
downView->lable2.text = @"小时";
downView->minutesTenLable.text = @"5";
downView->minutesBitsLable.text = @"8";
downView->lable3.text = @"分";
downView->secondsTenLable.text = @"5";
downView->secondsBitsLable.text = @"0";
downView->lable4.text = @"秒";
[self.view addSubview:downView];