iOS自定义控件之倒计时器
来源:互联网 发布:英国留学移民知乎 编辑:程序博客网 时间:2024/04/28 18:31
本文将介绍一个拥有圆环形状的倒计时器,涉及到的主要内容有路径绘制、动画、多线程和一些时间单位的相互转换,虽然这么多的内容看起来会很复杂,但跟着小编一步一步来实现,你就会发现原来可以这么简单。所以这里不再对这个控件作过多的陈述了,如果这样做的话是会在开头就出现一段不小的篇幅,我想这样你们是不会耐心看下去的(好吧,我承认是我太懒,没想到小学就学会的造句在今天看来是如此的艰难),不瞎扯了,直接上图吧。
----------------------------------------------------------------------------------------还是分割线------------------------------------------------------------------------------
完成效果图
----------------------------------------------------------------------------------------还是分割线------------------------------------------------------------------------------
1. 创建我们的GYCCircularTimer类
- 在Xcode里新建一个类,取名GYCCircularTimer,继承UIView
- 打开GYCCircularTimer.h文件,先从添加属性成员开始,想想一个倒计时器有哪些属性?看图!得有个用于显示它名字的Label吧、还得有个显示剩余时间的Label,圆环这样形状的用半径就可以表示出它的大小了吧、前面的环形圈和后面的环形圈,想想都头大......上代码吧:
@property (assign, nonatomic) CGFloat radius;@property (strong, nonatomic) CAShapeLayer *foregroundLayer;@property (assign, nonatomic) CGFloat foregroundPathWidth;@property (strong, nonatomic) UIColor *foregroundPathColor;@property (strong, nonatomic) CAShapeLayer *backgroundLayer;@property (assign, nonatomic) CGFloat backgroundPathWidth;@property (strong, nonatomic) UIColor *backgroundPathColor;@property (strong, nonatomic) UIView *contentView;@property (strong, nonatomic) UILabel *titleLabel;@property (strong, nonatomic) UILabel *timeLabel;@property (assign, nonatomic) id <CircularTimerDelegate> delegata;
我没说让读者就照这样写,怎么声明一个类的属性成员我想还是挺有讲究的吧,所以你大可按你自己的方式来定义类成员,但你够懒的话就直接Copy吧,这里另外定义了一个delegate,后面会用到,这里先添加以下代码到文件顶部位置:
@protocol CircularTimerDelegate <NSObject>- (void)finishedCountDown;@end
那么接下来就是公共接口的方法了(说明都写在注释里了,对就是给你看绿色字体来着):
/** * 初始化CircularTimer * * @param center 圆心位置 * @param r 半径 * @param width 线宽 * @param color 颜色 * @param isClockWise 是否顺时针 * @param t 标题 * @param h 小时 * @param m 分钟 * @param s 秒 * * @return CircularTimer实例 */- (instancetype)initWithCenter:(CGPoint)center Radius:(CGFloat)r PathWidth:(CGFloat )width PathColor:(UIColor *)color Clockwise:(BOOL)isClockWise Title:(NSString *)t Hour:(NSUInteger)h Minute:(NSUInteger)m Second:(NSUInteger)s;/** * 开始记时 */- (void)startCount;/** * 暂停 */- (void)pauseCount;/** * 继续 */- (void)resumeCount;/** * 停止 */- (void)stopCount;/** * 设置前景进度条 * * @param width 宽度 * @param color 颜色 */- (void)setForegroundProcessWidth:(CGFloat)width Color:(UIColor *)color;/** * 设置背景进度条 * * @param width 宽度 * @param color 颜色 */- (void)setBackgroundProcessWidth:(CGFloat)width Color:(UIColor *)color;/** * 设置标题 * * @param size 字体大小 * @param color 字体颜色 */- (void)setTitleFontSize:(CGFloat)size Color:(UIColor *)color;/** * 设置时间 * * @param size 字体大小 * @param color 字体颜色 */- (void)setTimeFontSize:(CGFloat)size Color:(UIColor *)color;
- 让我们看看.m文件里需要做的准备工作有哪些(当然是还是声明我们需要的变量啦):
@interface GYCCircularTimer () { //一个环形路径变量 UIBezierPath *path; //最初设置的总时长 NSInteger duration; //剩余时间 NSInteger remain; //缓存倒计时器的标题文本内容 NSString *title; //小时 NSUInteger hour; //分钟 NSUInteger minute; //秒 NSUInteger second; //用于倒计时的NSTimer对象变量 NSTimer *countDownTimer;}@end
GYCCircularTimer类的准备工作到此结束,接下来就是具体的实现。
2. 那么开始实现吧
- 这次我们首先来完成倒计时器里面控件的布局和基本属性设置,先来看看initCircularTimer方法吧:
- (void)initCircularTimer { //设置背景环形圈 self.backgroundLayer = [CAShapeLayer layer]; [self.backgroundLayer setPath:[path CGPath]]; [self.backgroundLayer setFillColor:[[UIColor clearColor] CGColor]]; [self.backgroundLayer setStrokeColor:[self.backgroundPathColor CGColor]]; [self.backgroundLayer setLineWidth:self.backgroundPathWidth]; [self.layer addSublayer:self.backgroundLayer]; //设置前景环形圈 self.foregroundLayer = [CAShapeLayer layer]; [self.foregroundLayer setPath:[path CGPath]]; [self.foregroundLayer setFillColor:[[UIColor clearColor] CGColor]]; [self.foregroundLayer setStrokeColor:[self.foregroundPathColor CGColor]]; [self.foregroundLayer setLineWidth:self.foregroundPathWidth]; [self.foregroundLayer setStrokeEnd:0]; [self.layer addSublayer:self.foregroundLayer]; //内容视图包括标题的显示和时间的倒数 self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)/3)]; [self.contentView setCenter:CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds))]; [self addSubview:self.contentView]; //设置标题的Label self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.contentView.bounds), CGRectGetHeight(self.contentView.bounds)/2)]; [self.titleLabel setText:title]; [self.titleLabel setTextColor:[UIColor darkGrayColor]]; [self.titleLabel setTextAlignment:NSTextAlignmentCenter]; [self.contentView addSubview:self.titleLabel]; //设置倒计时的Label self.timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.titleLabel.bounds), CGRectGetWidth(self.titleLabel.bounds), CGRectGetHeight(self.titleLabel.bounds))]; //设置时间格式为00:00:00 [self.timeLabel setText:[NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second]]; [self.timeLabel setTextColor:[UIColor darkGrayColor]]; [self.timeLabel setTextAlignment:NSTextAlignmentCenter]; [self.contentView addSubview:self.timeLabel];}
- 然后实现类的初始化方法initWithCenter:
- (instancetype)initWithCenter:(CGPoint)center Radius:(CGFloat)r PathWidth:(CGFloat)width PathColor:(UIColor *)color Clockwise:(BOOL)isClockWise Title:(NSString *)t Hour:(NSUInteger)h Minute:(NSUInteger)m Second:(NSUInteger)s { self = [super initWithFrame:CGRectMake(center.x-r, center.y-r, r*2, r*2)]; if (self) { //设置path的路径为一个环形,这里从0°开始是3点钟水平方向,增大角度是顺时针方向,那么要实现秒表从12点钟开始旋转的轨迹,就得把开始角度设置为-90°,结束角度设置270°,是否顺时针转动由参数isClockWise决定。 path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)) radius:r startAngle:-0.5*M_PI endAngle:1.5*M_PI clockwise:isClockWise]; //算出总的时长 duration = h*3600 + m*60 + s; //刚开始的剩余时间就等于总时长 remain = duration; self.foregroundPathColor = color; self.foregroundPathWidth = width; self.backgroundPathColor = [UIColor darkGrayColor]; self.backgroundPathWidth = width; title = t; hour = h; minute = m; second = s; [self initCircularTimer]; } return self;}
- 顺便把这两个改变环形进度条宽度和颜色的也给做了:
- (void)setForegroundProcessWidth:(CGFloat)width Color:(UIColor *)color { [self.foregroundLayer setLineWidth:width]; [self.foregroundLayer setStrokeColor:[color CGColor]];}- (void)setBackgroundProcessWidth:(CGFloat)width Color:(UIColor *)color { [self.backgroundLayer setLineWidth:width]; [self.backgroundLayer setBackgroundColor:[color CGColor]];}
- 接下来就是重点实现部分了,先从环形进度条的动画开始切入:
#pragma mark - count methods- (void)startCount { //将总时长细分成小时、分钟和秒,并按规定格式00:00:00显示出来 remain = duration; hour = (remain / 3600); minute = (remain / 60) % 60; second = (remain % 60); [self.timeLabel setText:[NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second]]; [self startAnimation]; if ([countDownTimer isValid]) { [countDownTimer invalidate]; } //开辟一个线程用于执行countDown方法,每一秒执行一次并一直重复下去。 countDownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countDown) userInfo:nil repeats:YES];}- (void)pauseCount { [self pauseAnimation]; [countDownTimer invalidate];}- (void)resumeCount { [self resumeAnimation]; [countDownTimer fire];}- (void)stopCount { remain = 0; [self stopAnimation]; [countDownTimer invalidate]; [self countDown];}- (void)countDown { //剩余时间进行自减 remain--; if (remain < 0) { //完成倒计时 remain = 0; [countDownTimer invalidate]; [self.timeLabel setText:@"00:00:00"]; //调用委托方法finishedCountDown [delegate performSelector:@selector(finishedCountDown)]; } else { //将剩余时间转换成时分秒 hour = (remain / 3600); minute = (remain / 60) % 60; second = (remain % 60); //然后显示在timeLabel上 [self.timeLabel setText:[NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second]]; } NSLog(@"%d", remain);}
基本内容到此都实现完成,还有两个方法setTitleFontSize和setTimeFontSize读者可以自己去试着编写(作者又偷懒了!怎么?就是这么任性...)。
3. 跑一遍
写到这其实发现内容也不多的吧......总算可以来看看成果了。
- 新建一个视图控制器,打开.m文件,在顶部导入GYCCircularTimer.h文件后添加如下代码:
@interface GYCCircularTimerViewController () <CircularTimerDelegate>{ GYCCircularTimer *cTimer; UIButton *cButton;}
- 再在viewDidLoad中进行编写,代码参照下面:
cTimer = [[GYCCircularTimer alloc] initWithCenter:CGPointMake(160, 160) Radius:100 PathWidth:5 PathColor:[UIColor brownColor] Clockwise:YES Title:@"完成倒计时" Hour:0 Minute:0 Second:10]; cTimer.delegate = self; [cTimer setBackgroundProcessWidth:11 Color:[UIColor darkGrayColor]]; [cTimer setForegroundProcessWidth:9 Color:[UIColor whiteColor]]; [cTimer.titleLabel setFont:[UIFont systemFontOfSize:12]]; [cTimer.titleLabel setTextColor:[UIColor lightGrayColor]]; [cTimer.titleLabel setBackgroundColor:[UIColor clearColor]]; [cTimer.timeLabel setFont:[UIFont boldSystemFontOfSize:18]]; [cTimer.timeLabel setTextColor:[UIColor darkGrayColor]]; [cTimer.timeLabel setBackgroundColor:[UIColor clearColor]]; [self.view addSubview:cTimer]; cButton = [[UIButton alloc] initWithFrame:CGRectMake(40, 320, 240, 40)]; [cButton setTitle:@"开始" forState:UIControlStateNormal]; [cButton setBackgroundColor:[UIColor darkGrayColor]]; [cButton addTarget:self action:@selector(clickedToStart) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:cButton];
- 定义个开始倒计时和暂停的方法:
- (void)clickedToStart { NSLog(@"开始记时..."); [cTimer startCount]; [cButton setTitle:@"暂停" forState:UIControlStateNormal]; [cButton setBackgroundColor:[UIColor lightGrayColor]]; [cButton removeTarget:self action:@selector(clickedToStart) forControlEvents:UIControlEventTouchUpInside]; [cButton addTarget:self action:@selector(clickedToPause) forControlEvents:UIControlEventTouchUpInside];}- (void)clickedToPause { NSLog(@"暂停"); [cTimer pauseCount]; [cButton setTitle:@"重新开始" forState:UIControlStateNormal]; [cButton setBackgroundColor:[UIColor darkGrayColor]]; [cButton removeTarget:self action:@selector(clickedToPause) forControlEvents:UIControlEventTouchUpInside]; [cButton addTarget:self action:@selector(clickedToStart) forControlEvents:UIControlEventTouchUpInside];}
- 实现GYCCircularTime类的代理方法:
#pragma mark - circular timer delegate- (void)finishedCountDown { NSLog(@"完成倒计时"); [cButton setTitle:@"开始" forState:UIControlStateNormal]; [cButton setBackgroundColor:[UIColor darkGrayColor]]; [cButton removeTarget:self action:@selector(clickedToPause) forControlEvents:UIControlEventTouchUpInside]; [cButton addTarget:self action:@selector(clickedToStart) forControlEvents:UIControlEventTouchUpInside];}
完成后,就可以编译运行!
----------------------------------------------------------------------------------------华丽分割线------------------------------------------------------------------------------
文章有错之处,自行改之,不要指正(就是这么傲娇还带卖萌的...啧啧),让“我”安静得当一个美男子吧!
完!!!
源码下载地址:https://github.com/ganyuchuan/GYCBox,详见GYCCircularTimer。
请别猛戳!!!
0 0
- iOS自定义控件之倒计时器
- iOS自定义控件之倒计时器
- iOS之UIDatePicker实现倒计时器
- 自定义倒计时器
- iOS 倒计时器
- Javascript技巧之计时器和倒计时器
- Javascript案例之计时器和倒计时器
- Android 自定义View -- 简单的倒计时器
- wpf自定义计时器控件
- 倒计时器
- 倒计时器
- 倒计时器
- 倒计时器
- 倒计时器
- 倒计时器
- 倒计时器
- 倒计时器
- iOS控件NSTimer计时器
- 2014年福建省大学生电子设计竞赛测控组参赛心得讲稿
- android笔记14-Gallery
- 找出数组中有元素比它的邻居大的元素下标
- android笔记15-AlertDialog
- 通过CCID获得各个段的描述的方法
- iOS自定义控件之倒计时器
- 数据结构---单链表
- bzoj 2806: [Ctsc2012]Cheat
- 网页制作中遇到的小问题(2)
- HTML文件基本标记
- OC语言细节总结
- 怎么样判断两个工程师谁的代码能力强
- 单词数
- 8.4.3 C# 决策树