一个play方法实现全屏炫酷倒计时的小demo
2016-12-07 14:18
381 查看
今天实现了下全屏倒计时的小demo并且简单的封装了一下,保证了其封装性和扩展性。只需在你的工程中倒入
先看效果:
![](https://raw.githubusercontent.com/WZBbiao/WZBCountdownLabel/master/demoGif.gif)
全屏动画效果
其实功能本身很简单,就是动画改变label的文字,然而我觉得封装很重要,我见过一个界面十几个功能,代码几千行,我觉得这样很不好,一来其它人看你代码的时候会晕头转向,找不着东南西北,二来不利于代码的维护和扩展。
而我在项目中往往会把一个界面的功能分为几大类,然后分模块实现这些功能,外部只需要提供几个简单的方法就可以实现,这样能够很大程度上简化代码,几千行的控制器只剩几百行甚至几十行,这样是不是很爽!
有人可能会说,你这倒计时3秒,不符合我的需求,我要5秒怎么办?简单!只需要用这个方法
有人可能会说,你这还不能满足我的需求,我要在5秒之后显示一个文字,怎么办?简单!只需要用这个方法
有人可能会说,你这还不能满足我的需求,我要在5秒文字显示完成之后做一些其它操作,怎么办?简单!我提供了两种方法通知控制器,没错,代理和block。首先签订协议让控制器成为此label的代理,因为一直用的类方法,所以绑定代理同样是提供一个类方法:
block是这样用的:
有人可能还会说,这样还是不能满足我的需求,我想要在开始动画的时候做些事情。这个监听也是有的:
block
delegate
需要注意的是:为了顺利执行,block和代理的绑定,必须要放在play方法的前面,不然会监听不到
最后,我提供了一个方法可以一行代码实现以上所有功能,look me:
下面简单讲下我的实现部分
上面这几个方法最终都会走到下边这个方法,核心代码:
本demo中的label并不是加在window上的,因为我发现这样会有问题。就是在动画还未结束的时候,界面跳转了,我想大多需求是需要隐藏这个倒计时的,但如果加在window上label不会隐藏。所以我选择把label加在当前控制器的view上
最后,
demo在这
如果喜欢我的文章,记得点击喜欢或者关注我哦!
文/杂雾无尘(简书作者)
原文链接:http://www.jianshu.com/p/43a6e362f1a3
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
#import "WZBCountdownLabel.h",在需要开始倒计时的地方使用
[WZBCountdownLabel play];即可!
先看效果:
![](https://raw.githubusercontent.com/WZBbiao/WZBCountdownLabel/master/demoGif.gif)
全屏动画效果
其实功能本身很简单,就是动画改变label的文字,然而我觉得封装很重要,我见过一个界面十几个功能,代码几千行,我觉得这样很不好,一来其它人看你代码的时候会晕头转向,找不着东南西北,二来不利于代码的维护和扩展。
而我在项目中往往会把一个界面的功能分为几大类,然后分模块实现这些功能,外部只需要提供几个简单的方法就可以实现,这样能够很大程度上简化代码,几千行的控制器只剩几百行甚至几十行,这样是不是很爽!
有人可能会说,你这倒计时3秒,不符合我的需求,我要5秒怎么办?简单!只需要用这个方法
[WZBCountdownLabel playWithNumber:5];。
有人可能会说,你这还不能满足我的需求,我要在5秒之后显示一个文字,怎么办?简单!只需要用这个方法
[WZBCountdownLabel playWithNumber:5 endTitle:@"GO!"];
有人可能会说,你这还不能满足我的需求,我要在5秒文字显示完成之后做一些其它操作,怎么办?简单!我提供了两种方法通知控制器,没错,代理和block。首先签订协议让控制器成为此label的代理,因为一直用的类方法,所以绑定代理同样是提供一个类方法:
[WZBCountdownLabel addDelegate:self];然后实现代理方法即可:
- (void)countdownSuccess:(WZBCountdownLabel *)label { // do something }
block是这样用的:
[WZBCountdownLabel setCountdownSuccessBlock:^(WZBCountdownLabel *label) { // countdown success }];
有人可能还会说,这样还是不能满足我的需求,我想要在开始动画的时候做些事情。这个监听也是有的:
block
[WZBCountdownLabel addCountdownBeginBlock:^(WZBCountdownLabel *label) { // countdown begin }];
delegate
- (void)countdownBegin:(WZBCountdownLabel *)label { NSLog(@"delegateBegin"); }
需要注意的是:为了顺利执行,block和代理的绑定,必须要放在play方法的前面,不然会监听不到
最后,我提供了一个方法可以一行代码实现以上所有功能,look me:
/* * return WZBCountdownLabel对象 * number : 倒计时开始的数字 * endTitle : 结束语 * begin : 倒计时开始的回调 * success : 倒计时成功的回调 */ [WZBCountdownLabel playWithNumber:5 endTitle:@"GO" begin:^(WZBCountdownLabel *label) { NSLog(@"blockBegin"); } success:^(WZBCountdownLabel *label) { NSLog(@"blockSuccess"); }];
下面简单讲下我的实现部分
+ (instancetype)play { return [self playWithNumber:0]; } + (instancetype)playWithNumber:(NSInteger)number { return [self playWithNumber:number endTitle:nil]; } + (instancetype)playWithNumber:(NSInteger)number endTitle:(NSString *)endTitle { return [self playWithNumber:number endTitle:endTitle success:nil]; } + (instancetype)playWithNumber:(NSInteger)number success:(CountdownSuccessBlock)success { return [self playWithNumber:number endTitle:nil success:success]; }
上面这几个方法最终都会走到下边这个方法,核心代码:
+ (instancetype)playWithNumber:(NSInteger)number endTitle:(NSString *)endTitle begin:(CountdownBeginBlock)begin success:(CountdownSuccessBlock)success { // isAnimationing 用来判断目前是否在动画 if (isAnimationing) return nil; WZBCountdownLabel *label = [WZBCountdownLabel share]; label.hidden = NO; // 给全局属性赋值 // 默认三秒 label.number = 3; if (number && number > 0) label.number = number; if (endTitle) label.endTitle = endTitle; if (success) label.countdownSuccessBlock = success; if (begin) label.countdownBeginBlock = begin; [self setupLabelBase:label]; // 动画倒计时部分 [self scaleActionWithBeginBlock:begin andSuccessBlock:success label:label]; return label; } // 动画倒计时部分 + (void)scaleActionWithBeginBlock:(CountdownBeginBlock)begin andSuccessBlock:(CountdownSuccessBlock)success label:(WZBCountdownLabel *)label { if (!isAnimationing) { // 如果不在动画才走开始的代理和block if (begin) begin(label); if ([label.delegate respondsToSelector:@selector(countdownBegin:)]) [label.delegate countdownBegin:label]; } // 这个判断用来表示有没有结束语 if (label.number >= (label.endTitle ? 0 : 1)) { isAnimationing = YES; label.text = label.number == 0 ? label.endTitle : [NSString stringWithFormat:@"%zd", label.number]; [UIView animateWithDuration:1 animations:^{ label.transform = CGAffineTransformIdentity; label.alpha = 1; } completion:^(BOOL finished) { if (finished) { label.number--; label.alpha = 0; label.transform = CGAffineTransformScale(label.transform, 10, 10); [self scaleActionWithBeginBlock:begin andSuccessBlock:success label:label]; } }]; } else { // 调用倒计时完成的代理和block if ([label.delegate respondsToSelector:@selector(countdownSuccess:)]) [label.delegate countdownSuccess:label]; if (success) success(label); [self hidden]; } }
本demo中的label并不是加在window上的,因为我发现这样会有问题。就是在动画还未结束的时候,界面跳转了,我想大多需求是需要隐藏这个倒计时的,但如果加在window上label不会隐藏。所以我选择把label加在当前控制器的view上
/// 这个方法是拿到当前正在显示的控制器,不管是push进去的,还是present进去的都能拿到,相信很多项目会用到。拿去不谢! - (UIViewController *)getVisibleViewControllerFrom:(UIViewController*)vc { if ([vc isKindOfClass:[UINavigationController class]]) { return [self getVisibleViewControllerFrom:[((UINavigationController*) vc) visibleViewController]]; }else if ([vc isKindOfClass:[UITabBarController class]]){ return [self getVisibleViewControllerFrom:[((UITabBarController*) vc) selectedViewController]]; } else { if (vc.presentedViewController) { return [self getVisibleViewControllerFrom:vc.presentedViewController]; } else { return vc; } } }
最后,
demo在这
如果喜欢我的文章,记得点击喜欢或者关注我哦!
文/杂雾无尘(简书作者)
原文链接:http://www.jianshu.com/p/43a6e362f1a3
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
相关文章推荐
- 详解Asp.net Core 使用Redis存储Session
- Block 的使用
- Ubuntu 音效均衡器,网易云音乐均衡器插件
- Linux内核中的GPIO系统之(3):pin controller driver代码分析
- 字符编码笔记:ASCII,Unicode和UTF-8(转)
- 字符编码笔记:ASCII,Unicode和UTF-8(转)
- 字符编码笔记:ASCII,Unicode和UTF-8(转)
- LinuxShell脚本攻略--第二章 命令之乐
- IntelliJ IDEA + Maven环境编写第一个hadoop程序
- 在jsp中获取服务器端的时间
- ELK之nginx日志分析图表创建
- w3c标准
- 3、MyEclipse中hadoop环境配置
- yolov1在ubuntu环境下的安装配置
- 修改PHP 上传文件大小限制
- oracle 判断今天是星期几
- 二维码 条形码
- 查看SELinux状态&关闭SELinux
- MySQL多配置方式的多实例的部署
- 傅里叶级数和傅里叶变换(从线性代数角度)