17-UIKit(UIView的动画)
2. UIView的动画
UIView类本身具有动画的功能
2.1 概念
由UI对底层Core Animation框架的封装
可以轻松简单的实现动画效果
2.2 两种使用方式
1> Block
基本步骤
1>设置参与动画的视图的初始状态 alpha=0.0
2>[UIView animateWithDuration:]
3>将结束状态写到block中
例1
- (IBAction)start:(id)sender { [UIView animateWithDuration:3.0 animations:^{ self.imageView.alpha = 1.0;// 目标值 }]; }
例2
// 界面显示后调用此方法,一般用来设置动画 -(void)viewDidAppear:(BOOL)animated{ // label动画 [super viewDidAppear:animated]; CGRect endFrame = self.label.frame; CGRect startFrame = endFrame; startFrame.origin.x = - self.label.frame.size.width; self.label.frame = startFrame;// frame开始值 self.label.alpha = 0;// 透明度开始值 [UIView animateWithDuration:2.0 animations:^{ self.label.frame = endFrame;// frame结束值 self.label.alpha = 1.0;// 透明度结束值 }]; // 飞机入场 self.imageView.image = [UIImage animatedImageNamed:@"ship-anim" duration:1.0]; endFrame = self.imageView.frame; startFrame = endFrame; startFrame.origin.y = self.view.frame.size.height; self.imageView.frame = startFrame; [UIView animateWithDuration:2.0 animations:^{ self.imageView.frame = endFrame; }]; } - (IBAction)start:(id)sender { CGPoint center = self.imageView.center; center.y -= 250; // CGAffineTransform transform = CGAffineTransformRotate(self.imageView.transform, M_PI); // CGAffineTransform transform = CGAffineTransformMakeScale(1.5, 1.5); // Duration动画时长 delay延迟 [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{ self.imageView.center = center; // self.imageView.transform = transform; } completion:nil]; } - (IBAction)back:(id)sender { CGRect endFrame = self.imageView.frame; endFrame.origin.y += 250; [UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.imageView.frame = endFrame; } completion:nil]; }
例3
-(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; [self animateOnView:self.imageView duration:1.0 clockWise:NO];// clockWise YES顺时针 } -(void)animateOnView:(UIView *)view duration:(NSTimeInterval)duration clockWise:(BOOL)clockWise{ // completion动画结束要做的事 [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ view.transform = CGAffineTransformRotate(view.transform, M_PI_2 * (clockWise ? 1 : -1)); } completion:^(BOOL finished) { if (!self.needStoped) { // 递归调用 [self animateOnView:view duration:duration clockWise:clockWise]; } }]; } // 停止动画 - (IBAction)stopAnimation:(id)sender { self.needStoped = YES; } // 恢复动画 - (IBAction)startAnimation:(id)sender { self.needStoped = NO; [self viewDidAppear:YES]; }
2> Commit
-(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; // 1开始一个动画,给动画起个名字, [UIView beginAnimations:@"snow" context:nil]; // 2设置动画相关属性 [UIView setAnimationDuration:4.0]; [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; // 3动画目标值 self.snow.center = CGPointMake(self.snow.center.x, self.view.bounds.size.height - self.snow.frame.size.height); // 4提交动画,动画开始 [UIView commitAnimations]; }
2.3 什么属性能做动画的设置属性
.frame
.bounds
.center
.transform
.alpha
等
稍复杂的动画[MX6-飘雪花练习]
#define MAX_SIZE 10 #define MAX_DURATION 5//速度 #define MAX_OFFSET_X 100 #define FPS 30 #define DISAPPER_DURATION 2 @interface MXViewController () @property(nonatomic) NSInteger count; @property(nonatomic,strong) NSTimer *timer; @end @implementation MXViewController - (void)viewDidLoad { [super viewDidLoad]; // [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(viewDidAppear:) userInfo:nil repeats:YES]; self.timeInterVal = 1/FPS; } -(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; [NSTimer scheduledTimerWithTimeInterval:self.timeInterVal target:self selector:@selector(generatorSnow) userInfo:nil repeats:YES]; } // 生成雪片 -(void)generatorSnow{ self.count++; // 创建随机大小的雪花 NSInteger size = arc4random() % MAX_SIZE + MAX_SIZE; UIImageView *snow = [[UIImageView alloc] initWithFrame:CGRectMake(arc4random() % 320, 20, size, size)]; snow.image = [UIImage imageNamed:@"snow.png"]; snow.tag = self.count; // 加入到父视图中 [self.view addSubview:snow]; // 创建动画 [UIView beginAnimations:[NSString stringWithFormat:@"%d",self.count] context:nil]; [UIView setAnimationDuration:arc4random() % MAX_DURATION + 2]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; // 设置了delegate,动画结束后才会自动调用disappearAnimate: [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(disappearAnimate:)];// 动画结束后调用disappearAnimate NSInteger offSetX = arc4random() % MAX_OFFSET_X - 50; // 设置动画目标值 snow.center = CGPointMake(snow.center.x + offSetX, self.view.bounds.size.height - 30); snow.transform = CGAffineTransformMakeRotation((arc4random() % 180)/180 * M_PI * 2); [UIView commitAnimations]; } - (IBAction)changeSnow:(UISlider *)sender { CGFloat value = sender.maximumValue - sender.value; self.timeInterVal = value * FPS; [self.timer invalidate]; self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeInterVal target:self selector:@selector(generatorSnow) userInfo:nil repeats:YES]; } // 雪花消失 -(void)disappearAnimate:(NSString *)animationId{ [UIView beginAnimations:animationId context:nil]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [UIView setAnimationDuration:arc4random() % DISAPPER_DURATION + 1]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(deleteView:)]; UIImageView *snow = (UIImageView *)[self.view viewWithTag:[animationId intValue]]; snow.alpha = 0; [UIView commitAnimations]; } // 删除雪花对象 -(void)deleteView:(NSString *)animationId{ UIImageView *snow = (UIImageView *)[self.view viewWithTag:[animationId intValue]]; [snow removeFromSuperview];// 删除子视图的方式 // NSLog(@"雪花对象:%p,雪花数量:%d",snow,[self.view subviews].count); }
2.4 UIView执行动画的方法:
[UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseIn animations:^{
self.playerView.frame = endFrame;
} completion:nil];
duration: 动画时长(秒)
delay: 启动动画的延迟(秒)
animations:
设置动画结束后的状态
completion:
动画结束后需要做事的
options:
UIViewAnimationOptionCurveEaseInOut 动画先从慢到快,再从快到慢
UIViewAnimationOptionCurveEaseIn 越来越快
UIViewAnimationOptionCurveEaseOut 越来越慢
UIViewAnimationOptionCurveLinear 匀速
UIViewAnimationOptionAllowUserInteraction 在动画期间是否允许用户交互
UIViewAnimationOptionBeginFromCurrentState 动画要不要从当前位置开始,如果不选,那就从初始位置开始
UIViewAnimationOptionRepeat 动画重复执行
UIViewAnimationOptionAutoreverse 动画是否需要反向执行
UIViewAnimationOptionLayoutSubviews 当动画发生大小变化时,是否需要重新布局
UIViewAnimationOptionAllowAnimatedContent 在动画的同时要不要执行Redraw
旋转动画
2.5 UIView设置全局属性方式动画
1>设置开始状态
2>开始动画,并给动画命名
[UIView beginAnimations:@"动画名" ….];
3>设置动画相关属性
[UIView setAnimationDuration:…];
[UIView setAnimationCurve:…];
….
4>设置动画结束状态
5>提交动画
[UIView commitsAnimation];
注意:
当设置了delegate后,DidStopSelector才会有效。
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(..)];
3. iOS7新增DynamicAnimator
@interface MXViewController () <UIDynamicAnimatorDelegate> @property(nonatomic,strong) UIDynamicAnimator *animator;// @property(nonatomic,strong) UIDynamicBehavior *behavior;// 行为(容器) @property(nonatomic,strong) UIGravityBehavior *gravity;// 重力 @property(nonatomic,strong) UICollisionBehavior *collision;// 碰撞 @end @implementation MXViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } -(UIGravityBehavior *)gravity{ if (!_gravity) { _gravity = [[UIGravityBehavior alloc] init]; _gravity.magnitude = 0.9;// 重力值 } return _gravity; } -(UICollisionBehavior *)collision{ if (!_collision) { _collision = [[UICollisionBehavior alloc] init]; _collision.translatesReferenceBoundsIntoBoundary = YES;// 周围边界翻译为碰撞边界 } return _collision; } -(UIDynamicBehavior *)behavior{ if (!_behavior) { _behavior = [[UIDynamicBehavior alloc] init]; [_behavior addChildBehavior:self.gravity]; [_behavior addChildBehavior:self.collision]; } return _behavior; } -(UIDynamicAnimator *)animator{ if (!_animator) { _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; _animator.delegate = self; } return _animator; } - (IBAction)dropTap:(id)sender { UIView *dropView = [[UIView alloc] initWithFrame:CGRectMake(arc4random() % 320, 100, 40, 40)]; dropView.backgroundColor = [self roundColor]; [self.view addSubview:dropView]; [self.gravity addItem:dropView]; [self.collision addItem:dropView]; [self.animator addBehavior:self.behavior]; } -(UIColor *)roundColor{ switch (arc4random() % 5) { case 0: return [UIColor greenColor]; break; case 1: return [UIColor grayColor]; break; case 2: return [UIColor redColor]; break; case 3: return [UIColor yellowColor]; break; case 4: return [UIColor blackColor]; break; default: break; } return nil; } -(void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator{ [animator removeBehavior:self.behavior]; }
作业:
1. 飞机大战Demo版
屏幕上有一个飞机,你点在屏幕的哪,飞机就飞到哪儿
2. 模仿一个淘宝的购物车
窗口左上角一个一图片,代表一个宝贝,点宝贝,会落入屏幕下方的一个小车车中,落下时,宝贝会越来越小,注意宝贝本身还在。
3. 简单看看UIDynamicAnimator文档