UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持。

UIViewAnimationOptions参考


1.基本类型
UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动。
UIViewAnimationOptionAllowUserInteraction:动画过程中允许用户交互。
UIViewAnimationOptionBeginFromCurrentState:所有视图从当前状态开始运行。
UIViewAnimationOptionRepeat:重复运行动画。
UIViewAnimationOptionAutoreverse :动画运行到结束点后仍然以动画方式回到初始点。
UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套动画时间设置。
UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套动画速度设置。
UIViewAnimationOptionAllowAnimatedContent:动画过程中重绘视图(注意仅仅适用于转场动画)。  
UIViewAnimationOptionShowHideTransitionViews:视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画)
UIViewAnimationOptionOverrideInheritedOptions :不继承父动画设置或动画类型。

2.动画速度控制(可从其中选择一个设置)
UIViewAnimationOptionCurveEaseInOut:动画先缓慢,然后逐渐加速。
UIViewAnimationOptionCurveEaseIn :动画逐渐变慢。
UIViewAnimationOptionCurveEaseOut:动画逐渐加速。
UIViewAnimationOptionCurveLinear :动画匀速执行,默认值。

3.转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)
UIViewAnimationOptionTransitionNone:没有转场动画效果。
UIViewAnimationOptionTransitionFlipFromLeft :从左侧翻转效果。
UIViewAnimationOptionTransitionFlipFromRight:从右侧翻转效果。
UIViewAnimationOptionTransitionCurlUp:向后翻页的动画过渡效果。    
UIViewAnimationOptionTransitionCurlDown :向前翻页的动画过渡效果。    
UIViewAnimationOptionTransitionCrossDissolve:旧视图溶解消失显示下一个新视图的效果。    
UIViewAnimationOptionTransitionFlipFromTop :从上方翻转效果。    
UIViewAnimationOptionTransitionFlipFromBottom:从底部翻转效果。

1. 基本动画

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

  • 参数详情:

duration   :   持续时间  
delay      :   延迟执行  
options    :   动画选项(往复、循环等)  
animations :   动画block  
completion :   完成后的block 
  • 可实现动画的属性

坐标尺寸类: bounds、frame、center  
视图显示类: backgroundColor、alpha、hidden  
形态变化类: transform

2.弹簧动画

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

  • 参数详情:
usingSpringWithDamping : 0.0 ~ 1.0 阻尼比例,数值越小「弹簧」的振动效果越明显
initialSpringVelocity : 初始的速度,数值越大一开始移动越快

3.过渡动画

+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

  • 参数详情:

view       :   需要进行转场动画的视图
options    :   转场动画的类型

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion

  • 参数详情:

方法调用完毕后,相当于执行了下面两句代码:
// 添加toView到父视图
[fromView.superview addSubview:toView];
// 把fromView从父视图中移除
[fromView removeFromSuperview];

4. keyframe动画

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations

  • 参数详情:
RelativeStartTime : 关键帧动画开始时间的比例值
RelativeDuration : 关键帧动画持续实践的比例值
  • 用法示例:

[UIView animateKeyframesWithDuration:8 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
        [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.25 animations:^{
            self.imgV.center = (CGPoint){center.x + 200 ,center.y + 150};
        }];
        [UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.25 animations:^{
            self.imgV.center = (CGPoint){center.x ,center.y + 300};
        }];
        [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
            self.imgV.center = (CGPoint){center.x + 200,center.y + 450};
        }];
        [UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
            self.imgV.center = (CGPoint){center.x + 0,center.y + 600 };
        }];
    } completion:nil];

5. transform变换

CGAffineTransform

  • 变换原理
struct CGAffineTransform {
CGFloat a;
CGFloat b;
CGFloat c;
CGFloat d;
CGFloat tx;
CGFloat ty;
};

结构体矩阵图为:


矩阵图

因为最后一列总是是(0,0,1),所以有用的信息就是前面两列
对一个view进行仿射变化就相当于对view上的每个点做一个乘法
结果就是:


映射变换

相当于:
(x, y, 1 ) –> (ax + cy + tx, bx + dy + ty, 1)

如果不看c和b的话
a表示x水平方向的缩放,tx表示x水平方向的偏移
d表示y垂直方向的缩放,ty表示y垂直方向的偏移
如果b和c不为零的话,那么视图肯定发生了旋转

常量
CGAffineTransformIdentity
CGAffineTransform
CGAffineTransformIdentity;
这个就是没有变化的最初的样子

  • 常用函数

/// 用来连接两个变换效果并返回。返回的t = t1 * t2
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2)

/// 矩阵初始值。[ 1 0 0 1 0 0 ]
CGAffineTransformIdentity

/// 自定义矩阵变换,需要掌握矩阵变换的知识才知道怎么用。参照(x, y, 1 ) --> (ax + cy + tx, bx + dy + ty, 1)  
CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)

/// 旋转视图。传入参数为 角度 * (M_PI / 180)。等同于 CGAffineTransformRotate(self.transform, angle)
CGAffineTransformMakeRotation(CGFloat angle)
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)

/// 缩放视图。等同于CGAffineTransformScale(self.transform, sx, sy)
CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)

/// 缩放视图。等同于CGAffineTransformTranslate(self.transform, tx, ty)
CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
  • 常用函数

- (void)viewDidAppear:(BOOL)animated {
    CGFloat offset = self.label1.frame.size.height * 0.5;

    self.label1.transform = CGAffineTransformConcat(
                                                    CGAffineTransformMakeScale(1, 0),
                                                    CGAffineTransformMakeTranslation(0, -offset));

    self.label1.alpha = 0;
    [UIView animateWithDuration:3.0 animations:^{
        self.label1.transform = CGAffineTransformIdentity;
        self.label1.alpha = 1;

        self.label2.transform = CGAffineTransformConcat(
                                                        CGAffineTransformMakeScale(1, 0.1),
                                                        CGAffineTransformMakeTranslation(0, offset));
        self.label2.alpha = 0;
    }];
}

6.UIView动画(首尾方式)

UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持
执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之间

常见方法解析:
  + (void)setAnimationDelegate:(id)delegate 设置动画代理对象,当动画开始或者结束时会发消息给代理对象
  + (void)setAnimationWillStartSelector:(SEL)selector 当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector
  + (void)setAnimationDidStopSelector:(SEL)selector 当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector
  + (void)setAnimationDuration:(NSTimeInterval)duration 动画的持续时间,秒为单位
  + (void)setAnimationDelay:(NSTimeInterval)delay 动画延迟delay秒后再开始
  + (void)setAnimationStartDate:(NSDate *)startDate 动画的开始时间,默认为now
  + (void)setAnimationCurve:(UIViewAnimationCurve)curve 动画的节奏控制
  + (void)setAnimationRepeatCount:(float)repeatCount 动画的重复次数
  + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses 如果设置为YES,代表动画每次重复执行的效果会跟上一次相反
  + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache 设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好

代码示例:


@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *customView;


@end

@implementation YYViewController

- (void)viewDidLoad
{
     [super viewDidLoad];

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
     //打印动画块的位置
     NSLog(@"动画执行之前的位置:%@",NSStringFromCGPoint(self.customView.center));

     //首尾式动画
     [UIView beginAnimations:nil context:nil];
     //执行动画
     //设置动画执行时间
     [UIView setAnimationDuration:2.0];
     //设置代理
     [UIView setAnimationDelegate:self];
     //设置动画执行完毕调用的事件
     [UIView setAnimationDidStopSelector:@selector(didStopAnimation)];
     self.customView.center=CGPointMake(200, 300);
     [UIView commitAnimations];

}

-(void)didStopAnimation
{
     NSLog(@"动画执行完毕");
     //打印动画块的位置
     NSLog(@"动画执行之后的位置:%@",NSStringFromCGPoint(self.customView.center));
}
@end

说明:
  使用UIView和CALayer都能实现动画效果,但是在真实的开发中,一般还是主要使用UIView封装的动画,而很少使用CALayer的动画。

CALayer核心动画与UIView动画的区别:
  UIView封装的动画执行完毕之后不会反弹。即如果是通过CALayer核心动画改变layer的位置状态,表面上看虽然已经改变了,但是实际上它的位置是没有改变的。

7.补充

UIImageView的帧动画

UIImageView可以让一系列的图片在特定的时间内按顺序显示

相关属性解析:
  animationImages:要显示的图片(一个装着UIImage的NSArray)
  animationDuration:完整地显示一次animationImages中的所有图片所需的时间
  animationRepeatCount:动画的执行次数(默认为0,代表无限循环)

相关方法解析:
  - (void)startAnimating; 开始动画
  - (void)stopAnimating; 停止动画
  - (BOOL)isAnimating; 是否正在运行动画

UIActivityIndicatorView

是一个旋转进度轮,可以用来告知用户有一个操作正在进行中,一般用initWithActivityIndicatorStyle初始化

相关方法解析:
  - (void)startAnimating; 开始动画
  - (void)stopAnimating; 停止动画
  - (BOOL)isAnimating; 是否正在运行动画

UIActivityIndicatorViewStyle有3个值可供选择:
  UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器
  UIActivityIndicatorViewStyleWhite //标准尺寸白色指示器
  UIActivityIndicatorViewStyleGray //灰色指示器,用于白色背景