#import "AnimationExplorerViewController.h"
#import "JSONExplorerViewController.h"
#import "LAQRScannerViewController.h"
#import <Lottie/Lottie.h>
typedef enum : NSUInteger {
ViewBackgroundColorWhite,
ViewBackgroundColorBlack,
ViewBackgroundColorGreen,
ViewBackgroundColorNone
} ViewBackgroundColor;
@interface AnimationExplorerViewController ()
@property (nonatomic, assign) ViewBackgroundColor currentBGColor;
@property (nonatomic, strong) UIToolbar *toolbar;
@property (nonatomic, strong) UISlider *slider;
/**
动画承载视图
*/
@property (nonatomic, strong) LOTAnimationView *laAnimation;
@end
@implementation AnimationExplorerViewController
- (void)setCurrentBGColor:(ViewBackgroundColor)currentBGColor {
_currentBGColor = currentBGColor;
switch (currentBGColor) {
case ViewBackgroundColorWhite:
self.view.backgroundColor = [UIColor whiteColor];
break;
case ViewBackgroundColorBlack:
self.view.backgroundColor = [UIColor blackColor];
break;
case ViewBackgroundColorGreen:
self.view.backgroundColor = [UIColor colorWithRed:50.f/255.f
green:207.f/255.f
blue:193.f/255.f
alpha:1.f];
break;
case ViewBackgroundColorNone:
self.view.backgroundColor = nil;
break;
default:
break;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.currentBGColor = ViewBackgroundColorWhite;
self.toolbar = [[UIToolbar alloc] initWithFrame:CGRectZero];
UIBarButtonItem *open = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(_open:)];
UIBarButtonItem *flx1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
//分享转发按钮 —— (需要 调用 “URL” 的方法来助推)
UIBarButtonItem *openWeb = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(_showURLInput)];
UIBarButtonItem *flx2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *play = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(_play:)];
UIBarButtonItem *flx3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *loop = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(_loop:)];
UIBarButtonItem *flx4 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *zoom = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(_setZoom:)];
UIBarButtonItem *flx5 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *bgcolor = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(_setBGColor:)];
UIBarButtonItem *flx6 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *close = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(_close:)];
self.toolbar.items = @[open, flx1, openWeb, flx2, loop, flx3, play, flx4, zoom, flx5, bgcolor, flx6, close];
[self.view addSubview:self.toolbar];
[self resetAllButtons];
self.slider = [[UISlider alloc] initWithFrame:CGRectZero];
[self.slider addTarget:self action:@selector(_sliderChanged:) forControlEvents:UIControlEventValueChanged];
self.slider.minimumValue = 0;
self.slider.maximumValue = 1;
[self.view addSubview:self.slider];
}
- 重新设置 所有按钮 的 显示效果
- (void)resetAllButtons {
self.slider.value = 0;
for (UIBarButtonItem *button in self.toolbar.items) {
[self resetButton:button highlighted:NO];
}
}
- 设置播放按钮的 颜色 (通过bool值来判断 当前按钮的 状态并为之赋予不同的颜色)
- (void)resetButton:(UIBarButtonItem *)button highlighted:(BOOL)highlighted {
//通过三目运算符来判断当前按钮的所处状态 点击“播放”后为黑色 :“其余按钮” 颜色为 “ :” 后的颜色
button.tintColor = highlighted ? [UIColor blackColor] : [UIColor colorWithRed:50.f/255.f
green:207.f/255.f
blue:193.f/255.f
alpha:1.f];
NSLog(@"播放按钮 当前 所处 状态为 :%@",highlighted ? @"黑色" : @"绿色");
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
CGRect b = self.view.bounds;
self.toolbar.frame = CGRectMake(0, b.size.height - 44, b.size.width, 44);
CGSize sliderSize = [self.slider sizeThatFits:b.size];
sliderSize.height += 12;
self.slider.frame = CGRectMake(10, CGRectGetMinY(self.toolbar.frame) - sliderSize.height, b.size.width - 20, sliderSize.height);
self.laAnimation.frame = CGRectMake(0, 0, b.size.width, CGRectGetMinY(self.slider.frame));
}
- 监听到 进度条的 位置 改变时 动态赋值给当前的 进度条 以 实时改变 UI
- (void)_sliderChanged:(UISlider *)slider {
self.laAnimation.animationProgress = slider.value;
NSLog(@"%f",slider.value);
}
- (void)_open:(UIBarButtonItem *)button {
[self _showJSONExplorer];
}
- 自己定义的枚举类型方法 ——(里面是三个 不同的 视图 显示位置类型)
- (void)_setZoom:(UIBarButtonItem *)button {
switch (self.laAnimation.contentMode) {
case UIViewContentModeScaleAspectFit: {
self.laAnimation.contentMode = UIViewContentModeScaleAspectFill;
[self showMessage:@"Aspect Fill"];
} break;
case UIViewContentModeScaleAspectFill:{
self.laAnimation.contentMode = UIViewContentModeScaleToFill;
[self showMessage:@"Scale Fill"];
}
break;
case UIViewContentModeScaleToFill: {
self.laAnimation.contentMode = UIViewContentModeScaleAspectFit;
[self showMessage:@"Aspect Fit"];
}
break;
default:
break;
}
}
- (void)_setBGColor:(UIBarButtonItem *)button {
ViewBackgroundColor current = self.currentBGColor;
current += 1;
if (current == ViewBackgroundColorNone) {
current = ViewBackgroundColorWhite;
}
self.currentBGColor = current;
}
- 通过“URL”的方式来获取 动画 的 内容文件 并解析
- (void)_showURLInput {
LAQRScannerViewController *qrVC = [[LAQRScannerViewController alloc] init];
[qrVC setCompletionBlock:^(NSString *selectedAnimation) {
if (selectedAnimation) {
//调用 下面当中的 “URL” 的方法
[self _loadAnimationFromURLString:selectedAnimation];
}
[self dismissViewControllerAnimated:YES completion:NULL];
}];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:qrVC];
[self presentViewController:nav animated:YES completion:NULL];
}
- 跳转到 列表 界面
- (void)_showJSONExplorer {
//跳转到 列表 界面
JSONExplorerViewController *vc = [[JSONExplorerViewController alloc] init];
//让 该控制器“vc” 去调动 一个 block的 回传属性方法
[vc setCompletionBlock:^(NSString *selectedAnimation) {
if (selectedAnimation) {
//并把 点中的 row cell的 动画名字 回传过去
[self _loadAnimationNamed:selectedAnimation];
NSLog(@"点中动画的名字:%@",selectedAnimation);
}
//执行完上边的block的方法后,自动向下弹走控制器
[self dismissViewControllerAnimated:YES completion:NULL];
}];
//把 ”列表“ 控制器 设置为 根视图控制器
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
//弹出模态ViewController(弹出控制器)
[self presentViewController:navController animated:YES completion:NULL];
}
- (void)_loadAnimationFromURLString:(NSString *)URL {
//跟下一个方法中的 意思 类同
[self.laAnimation removeFromSuperview];
self.laAnimation = nil;
[self resetAllButtons];
//跟下一个 方法中 不同的是 改方法中 是通过 “URL” 的路径字符串来 初始化 动画承载视图
self.laAnimation = [[LOTAnimationView alloc] initWithContentsOfURL:[NSURL URLWithString:URL]];
self.laAnimation.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:self.laAnimation];
[self.view setNeedsLayout];
}
- 移除 “动画承载视图” 上的现有内容 并 赋值为空 (nil)
- 不然~ 你将无法 选择 下一个 动画 展示在 视图上 ,因为 当前的 视图上已经有了 内容 并且你没有 及时 移除掉!
//上方block 中 所调用的方法
- (void)_loadAnimationNamed:(NSString *)named {
//移除 “动画承载视图” 上的现有内容 并 赋值为空 (nil)
//不然~ 你将无法 选择 下一个 动画 展示在 视图上 ,因为 当前的 视图上已经有了 内容 并且你没有 及时 移除掉!
[self.laAnimation removeFromSuperview];
self.laAnimation = nil;
//将所有的 按钮 位置 复原 —— (尤其是 时间进度条上的button,通过复原。使其值 变为 “0”,这样滑块 自然 处于 开始的位置)
//!!注意:如果不复原,滑块按钮 将位于 时间进度条的左右边既动画结束的位置!!
[self resetAllButtons];
//将上面 通过 点击某行 所传过来的 动画json文件名字 获取到 并 调用方法解析完后 满屏加载到 合适的 位置
self.laAnimation = [LOTAnimationView animationNamed:named];
self.laAnimation.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:self.laAnimation];
//将所需要的动画 加载到 当前视图 ——(此方法可写可不写)
[self.view setNeedsLayout];
}
重绕方法 —— (此方法 该类中 并没有 实际调用到,所以 可写可不写。不影响操作~)
- (void)_rewind:(UIBarButtonItem *)button {
//设置动画重载视图的 “进度”
//实现原理是将 后期 更改的 赋值给 之前的 进度属性
self.laAnimation.animationProgress = 0.5;
}
CADisplayLink是用于同步屏幕刷新频率的计时器,在开发中我们经常会遇到使用计时器的情况,例如图片轮播,进度条的绘制等就是比较常见的应用场景.
从runloop中移除
移除计时器有两个方法:
-- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode 和
-- (void)invalidate.
我们来分析一下他们的异同
removeFromRunLoop: forMode:会将接收者从给定的模式中移除,这个方法会对计时器进行隐式的release.
在调用removeFromRunloop方法,需要做判断,如果当期计时器不在runloop的话,会出现野指针的crash.
出现crash的原因是runloop多次调用了release方法,进行了over-release.
-- (void)invalidate是从runloop所有模式中移除计时器,并取消计时器和target的关联关系.多次调用这个方法,不会出现crash.
- (void)_play:(UIBarButtonItem *)button {
// isAnimationPlaying —— 播放动画时标志为YES 为 Bool 类型
//当检测到 该动画为 点击 “播放” 按钮后 即将进入 (动画正在播放ing) 的状态并执行下面的语句
if (self.laAnimation.isAnimationPlaying) {
//当处于(动画正在播放ing)的 状态时 再次点击 “播放” 按钮时 将会 暂停 "滑块" 以及 "动画" 并将 "播放" 按钮的颜色 改变~
//此刷新 按钮状态的 方法 可写可不写 并没任何影响
[self resetButton:button highlighted:NO];
[self.laAnimation pause];
} else {
//CADisplayLink是用于同步屏幕刷新频率的计时器,在开发中我们经常会遇到使用计时器的情况,例如图片轮播,进度条的绘制等就是比较常见的应用场景.
CADisplayLink *displayLink =[CADisplayLink displayLinkWithTarget:self selector:@selector(_updateSlider)] ;
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
//在此处,才是真正的 改变 “播放” 按钮的 颜色 状态
[self resetButton:button highlighted:YES];
[self.laAnimation playWithCompletion:^(BOOL animationFinished) {
//每个计时器对象只能加入到一个runloop中,但是可以被添加到不同的模式中,当CADisplayLink被加入到runloop时,会被runloop隐式retain.如果想从所有的模式中移除计时器,需要执行-invalidate()方法.
[displayLink invalidate];
[self resetButton:button highlighted:NO];
}];
}
}
- (void)_updateSlider {
//刷新 进度条的 变化
//将 当前 动画 的 播放进度 赋值给 进度条的 Value 值
self.slider.value = self.laAnimation.animationProgress;
}
- (void)_loop:(UIBarButtonItem *)button {
self.laAnimation.loopAnimation = !self.laAnimation.loopAnimation;
// loopAnimation :告诉动画 无限循环 —— 默认为NO
[self resetButton:button highlighted:self.laAnimation.loopAnimation];
//通过判断 按钮点击的 呈现状态(重复:不重复)
//来展示消息提示框 (Loop Enabled循环过程中" : @"Loop Disabled终止循环播放)
[self showMessage:self.laAnimation.loopAnimation ? @"Loop Enabled循环过程中" : @"Loop Disabled终止循环播放"];
}
- (void)_close:(UIBarButtonItem *)button {
[self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
}
- (void)showMessage:(NSString *)message {
UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectZero];
messageLabel.textAlignment = NSTextAlignmentCenter;
messageLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
messageLabel.textColor = [UIColor whiteColor];
messageLabel.text = message;
CGSize messageSize = [messageLabel sizeThatFits:self.view.bounds.size];
messageSize.width += 14;
messageSize.height += 14;
messageLabel.frame = CGRectMake(10, 30, messageSize.width, messageSize.height);
messageLabel.alpha = 0;
[self.view addSubview:messageLabel];
[UIView animateWithDuration:0.3 animations:^{
messageLabel.alpha = 1;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
messageLabel.alpha = 0;
} completion:^(BOOL finished) {
[messageLabel removeFromSuperview];
}];
}];
}
@end
网友评论