iOS 自动布局动画_图层


粉骨碎身全不怕, 要留清白在人间!<小拳石>



iOS 自动布局动画_动画效果_02


动画的思维导图



基础知识:
iOS能够实现动画的方式:(如上图)

  • UIView基础实现方式一
  • UIView基础实现方式二
  • CoreAnimation实现方式

动画的效果简述:

  • 传达状态
  • 提高用户对直接操作的感知
  • 帮助用户可视化操作的结果

UIVIew 的基础动画:

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

代码部分详细介绍相关属性


CALayer基本介绍:

  • CALayer负责绘制, 提供UIView需要展示的内容, 不能交互
  • UIView负责交互,显示CALayer绘制的内容
  • CALayer(层)是屏幕上的一个矩形区域, 在每一个UIView中都包含一个根
  • CALayer, 在UIView上的所以视觉效果都是在这个Layer上进行的.

1: 在 iOS 中, 我们能看见的, 例如按钮, 文本, 标签, 输入框, 等等 都是 UIView
2: 其实 UIView 之所以能显示在屏幕上, 完全是因为它内部的一个图层, 在创建 UIView 对象的时候, UIView 内部会自动创建一个图层就是(CALayer 对象), 通过 UIView 的 layer 属性就可以访问这个层
3: 当 UIView 需要显示到屏幕上时, 会调用 drawRect: 方法进行绘图, 并且将所有的绘制内容在自己的图层上绘制, 给图层绘制完毕后, 系统将会拷贝图层到屏幕上, 完成 UIView 的显示
4: UIVIew 本身是不具备显示功能的, 真正拥有显示功能的是里面的 layer 层
5: 通过 UIView 的图层, 可以调整 UIView 的一些界面属性, 例如阴影 圆角 边框 颜色

CALayer外形特征主要包括:

  • 层的大小尺寸
  • 背景色
  • 内容(可以填充图片或者使用Core Graphics绘制的内容)
  • 积习是否使用圆角
  • 矩形是否有阴影

CALayer常用属性:
与UIView动画相比, CoreAnimation能够实现更多复杂, 好看, 高效的动画效果:

  • 阴影, 圆角, 带颜色的边框
  • 3D变换
  • 透明遮罩
  • 多级非线性动画
  • CALayer的坐标系统比UIView多了一个anchorPoint属性
    anchorPoint锚点相对自身bounds来说,默认值为(0.5,0.5),即是anchorPoint的默认值在layer的中心点,它的值在0~1之间


  • iOS 自动布局动画_动画效果_03

  • 简单图示锚点

CoreAnimation动画

  • CoreAnimation动画位于iOS框架的Media层
  • CoreAnimation动画实现需要添加QuartzCore.Framework
  • CoreAnimation基本上是Layer Animation
  • CABasicAnimation基本单一类型的动画
  • CAKeyframeAnimation 帧动画, 主要操作属性与keyPath 和 values值组合
  • CAAnimationGroup组合动画, 操作属性: animations将CAAnimation类型的动画加入数组, FIFO队列的方式执行

1: 核心动画的基本概念

① core Animation, 核心动画, 是一组非常强大的动画处理 API, 可以用少量的代码, 实现强大的功能
② core Animation, 可以用在 Mac OS 和 iOS 两个平台
③ core Animation, 动画的执行过程, 都是在后台操作的, 所以不会阻塞主线程
④ core Animation, 是直接操作 CALayer 层的, 并不是 UIView

2: CAAnimation
① 所有动画的父类, 负责控制动画的持续时间和速度, 他是一个抽象的类, 不能直接使用, 应该使用他的子类
② 属性说明:

  • duration: 动画的持续时间
  • repeatCount: 动画的重复次数
  • repeatDuration: 重复时间
  • removeOnCompletion (BOOL): 默认为 YES, 表示动画执行完毕后就从图层上移除, 图形会恢复到执行之前的状态. 如果想要保持执行之后的状态, 那就设置 NO, 但是, 还需要设置 fillMode 值为 kCAFillModeForwards
  • fillModel: 决定当前对象在非活动的时间段的行为, 比如动画开始前或者动画结束之后 (想要 fillMode 有效, 最好将removeOnCompletion = 0);
  • kCAFillModeRemove:
    默认值也就是当前动画开始前和动画结束后, 动画对 layer 都没有影响, 动画结束后, layer 会恢复之前的状态
  • kCAFillModeForwards:
    当前结束动画后, layer 会一直保持最后的状态
  • kCAFillModeBackwards:
    在动画开始之前, 只需要将动画加入一个 layer, layer 便立即进入动画的初始状态并等待动画的开始.
  • kCAFillModeBoth: 就是上面两个 kCAFillModeForwards 和kCAFillModeBackwards 的合成
  • beginTime: 可以用来设置动画的延迟时间, 若想设置延迟 2秒, 那么就设置 CACurrentMediaTime() + 2 CACurrentMediaTime()图层当前的时间
  • timeFuncation: 速度控制函数 控制动画运行的节奏

---> CAMediaTimingFunctionLinear (线性): 匀速, 给你一个相对静态的感觉
---> CAMediaTimingFunctionEaseIn (淡入): 动画缓慢进入, 然后加速离开
---> CAMediaTimingFunctionEaseOut (淡出): 动画全速进入, 然后减速到达目的地
---> CAMediaTimingFunctionEaseInEaseOut (淡入淡出)

③ CAAnimation 的子类

  • CABasicAnimation
  • CALeyFrameAnimation
  • CAAnimationGroup
  • CASpringAnimation

④ 属性说明

  • keypath: 通过制定 CALayer 的一个属性名称为 keypath(NSString 类型) , 并且对 CALayer 这个属性值进行修改, 达到相应的动画效果, 比如, 制定@"postion"为 keypath , 就相当于修改了 CALayer 的 poison 属性的值,达到平移的动画效果.
  • 下面的代码部分会对这个 关建路径支持结构字段 进行相应的总结


iOS 自动布局动画_iOS 自动布局动画_04


关键路径支持的部分字段说明


  • 关键路径支持的部分字段补充说明

margin = 布局
zPosition = 翻转
backgroundColor = 背景颜色
cornerRadius = 圆角
borderWidth = 边框宽
bounds = 大小
contents = 内容
contentsRect = 内容大小
cornerRadius = 圆角
frame = 大小位置
hidden = 显示隐藏
mask 遮罩
masksToBounds
opacity 不透明的
position 位置
shadowColor 阴影颜色
shadowOffset 阴影偏移量
shadowOpacity 阴影不透明的
shadowRadius 阴影半径
transform.scale = 比例转换
transform.scale.x =以 x轴 比例转换
transform.scale.y = 以 y轴 比例转换
transform.rotation.z = 平面圆形旋转

3: 关键帧动画 与 CABasicAnimation 的区别
① CABasicAnimation只能从一个数值(fromvalue) 变换到另外一个数值 (tovaule)
② 关键帧动画, 会使用一个 NSArray 保存这些数值

4: 动画组
① 属性说明:

  • animations: 用来保存一组动画对象NSArray
  • 默认情况下, 一组动画对象是同时运动的, 也可以通过设置动画的 beginTime 属性来更改动画的开始时间

5: 转场动画 -------- CATransition: --------------
CATransition: 用于做转场动画效果, 能够为 layer 层提供移出屏幕和移入屏幕的动画效果
① 动画属性:

  • type: 动画的过渡效果

类型字符串 效果说明
fade 交叉淡化过渡
push 新视图把旧视图推出去
moveIn 新视图移到旧视图上面
reveal 将旧视图移开,显示下面的新视图
cube 立方体翻转效果
oglFlip 上下左右翻转效果
suckEffect 收缩效果,像一块布被抽走
rippleEffect 水滴效果
pageCurl 向上翻页效果
pageUnCurl 向下翻页效果

cameraIrisHollowOpen 相机镜头打开效果
cameraIrisHollowClose 相机镜头关闭效果

  • subtype: 动画的过渡方向
  • startProgress: 动画的起点(在整个动画的百分比)
  • endProgress: 动画的终点

UIView 的基础动画 代码总结
实例1: 自定义一个属性 MyLabel (UILabel)类型的 展示的是 UIView 的动画效果, 在一个触发方法里面实现动画,我这里写在 TouchBegin 里面.

//1. 创建一个动画
[UIView beginAnimations:nil context:nil];
//2. 动画延迟设置
[UIView setAnimationDelay:1];
//3. 给动画添加代理(不遵循代理协议, 也能实现代理方法)
[UIView setAnimationDelegate:self];
//4. 给动画添加方法(动画结束后执行)
[UIView setAnimationDidStopSelector:@selector(stopAc)];
//5. 动画持续时间(完成动画所需时间)
[UIView setAnimationDuration:2];
//6. 设置动画是否会做一次反向的执行  (等会属性里面再说)
[UIView setAnimationRepeatAutoreverses:YES];
//7. 设置动画移动的新位置
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
//8. 开始提交动画 (解释可以看下面)
[UIView commitAnimations];



iOS 自动布局动画_图层_05


基础动画--**这个 MyLabel 从开始的位置移动到新位置,设置了反向执行 YES 所以到达新位置后又反向移动了最后才来到新位置**


总结一下这里涉及的方法: 均是 UIView 的类方法

  • 第 1个方法: 动画马上开始:begin
+(void)beginAnimations:(NSString*)animationID context:(void *)context{}

# 参数1: animationID 作为动画的标示使用, 可以方便移除动画操作
# 参数2:  context 动画的设置 自定义的一些动画数据,这些数据将发送给动画的代理方法 默认 nil
  • 最后 1 个方法: commit
# 这个方法  就是提交动画 也是标记动画的内容已经编辑好了  可以使用效果了
+ (void)commitAnimations

在这两个方法之间就我们进行,动画相关的一些设置,下面是一些设置的方法

# 设置代理 及其 方法不需要设置遵循代理方法  默认 nil 没有代理
+ (void)setAnimationDelegate:(nullable id)delegate;                          
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;                
+ (void)setAnimationDidStopSelector:(nullable SEL)selector; 

# 设置动画持续时间     默认 = 0.2            
+ (void)setAnimationDuration:(NSTimeInterval)duration;  
# 设置动画的延迟时间 默认是不延迟 就是0.00            
+ (void)setAnimationDelay:(NSTimeInterval)delay;    
# 设置动画的开始时间     default = now ([NSDate date])        
+ (void)setAnimationStartDate:(NSDate *)startDate;   

# 设置动画的曲线方式(动画的总体变化的时间曲线:开始快最后慢,开始慢最后快,最后慢,均匀线性)  默认default = UIViewAnimationCurveEaseInOut
/*typedef NS_ENUM(NSInteger, UIViewAnimationCurve){
    UIViewAnimationCurveEaseInOut,    
    UIViewAnimationCurveEaseIn,     
    UIViewAnimationCurveEaseOut,     
    UIViewAnimationCurveLinear
  };
*/            
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;              

# 动画的重复次数 default = 0.0.  
+ (void)setAnimationRepeatCount:(float)repeatCount;                 

# 设置动画是否做一次反向的执行。
/*如果设置为YES:动画将执行:动画初始状态->动画->动画完成状态->动画->动画初始状态 。
如果设置为NO:默认值*/
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;    

# 设置动画的开始状态
/*
YES : 第一个动画正在 执行时候, 另一个动画恰好开始, 这样第一个动画的当前状态, 就是另一个动画的开始状态
NO: 第一个达到完成状态, 下一个动画才开始执行动画的效果
*/
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;  

# 设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好
/*
UIView官方提供五种动画效果供大家使用,分别为:
UIViewAnimationTransitionNone    不使用动画
UIViewAnimationTransitionFlipFromLeft    从左向右旋转翻页
UIViewAnimationTransitionFlipFromRight    从右向左旋转翻页
UIViewAnimationTransitionCurlUp    卷曲翻页,从下往上
UIViewAnimationTransitionCurlDown    卷曲翻页,从上往下
*/
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; 

# 设置view是否有动画效果
/*
YES: 默认有动画的能力
NO: 关闭动画效果
效果关闭并不会对 UI 的改变有什么影响只是不会 "动画" 了而已, 其他的大小什么属性依然有效的
*/  
+ (void)setAnimationsEnabled:(BOOL)enabled; 

# 判断当前的动画效果是否关闭了                  
+ (BOOL)areAnimationsEnabled;

通过 UIView 的几个 Block 方法进行动画设置

  • // 实现动画 的 Block1

参数1 : Duration 动画持续时间 Block 里面就写你要实现的效果(位置的改变等)

[UIView animateWithDuration:2 animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
}];

- // 实现动画 的 Block2 
```code
# 参数比上面多一个 动画结束后的操作
    [UIView animateWithDuration:2 animations:^{
        self.MyLabel.frame = CGRectMake(100, 100, 200, 200);
    } completion:^(BOOL finished) {
        NSLog(@"动画结束的操作可以写这里");
    }];```

- // 实现动画 的 Block3
 ```code   
   /* 
      参数1: Duration: 动画持续时间
      参数2: delay: 延迟时间
      参数3: options: 枚举值 动画的效果类型*/
  [UIView animateWithDuration:2 delay:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
        } completion:^(BOOL finished) {
NSLog(@"结束了%d", finished); 
}];```

-  //实现动画的Block4 弹簧效果
```code    
 /*
     Spring: 模拟弹簧弹跳的效果
     参数: Damping:阻尼 0-1 阻尼越小动画越明显
     参数: initialSpringVelocity : 动画初始变化速度
     参数: options  转变的风格  枚举值
*/
 [UIView animateWithDuration:10 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:15 options:(UIViewAnimationOptionCurveEaseInOut) animations:^{
        self.MyLabel.center = CGPointMake(self.view.center.x, 100);
    } completion:^(BOOL finished) {
        NSLog(@"弹簧效果结束");
 }];```

- //实现动画的Block5  关键帧动画 也就是里面有好几个动画进行转变
```code    
    /*
    Duration:持续时间
    delay: 延迟时间
     options: 枚举值  动画的风格
     */
[UIView animateKeyframesWithDuration:3   delay:0 options:(UIViewKeyframeAnimationOptionRepeat) animations:^{
/*
参数1: RelativeStartTime:  相对的开始时间
参数2: relativeDuration:相对持续时间
*/
         [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
            self.MyLabel.center = self.view.center;
        }];
        [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.3 animations:^{
            self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
        }];
           [UIView addKeyframeWithRelativeStartTime:0.8 relativeDuration:0.3 animations:^{
            self.MyLabel.frame = CGRectMake(100, 400, 100, 100);
        }];     
    } completion:^(BOOL finished) {
        NSLog(@"结束了");
    }];

  • CAAnimation 的子类
    ------------ CABasicAnimation -----------------
# 1: 创建  以字段为   旋转变换
    CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
# 动画效果的初始值
    basic.fromValue = @0;
# 动画效果变化的结束值 (绝对值)  这里就是旋转的角度从多少转到多少度
    basic.toValue = @(2*M_PI);
# 动画执行时间
    basic.duration = 5;
# Layer 动画需要天加到 layer 上    forkey 我们可以写上我们标记的动画属性    
[self.MyLabel.layer addAnimation:basic forKey:@"transform.rotation"];



iOS 自动布局动画_圆角_06


这个效果就是旋转360°(顺时针-->初始值比结束值小),



--------- CAKeyFramAnimation 关键帧动画--------

// 创建  以关键字段   位置变化
    CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//  建几个动画的位置
    CGPoint p1 = CGPointMake(0, 0);
    CGPoint p2 = CGPointMake(0, 400);
    CGPoint p3 = CGPointMake(400, 100);
    CGPoint p4 = CGPointMake(100, 200);
    CGPoint p5 = CGPointMake(200, 300);
    NSValue *v1 = [NSValue valueWithCGPoint:p1];
    NSValue *v2 = [NSValue valueWithCGPoint:p2];
    NSValue *v3 = [NSValue valueWithCGPoint:p3];
    NSValue *v4 = [NSValue valueWithCGPoint:p4];
    NSValue *v5 = [NSValue valueWithCGPoint:p5];
     //属性 values :  数组对象 里面的元素称为"keyFrame"(关键帧), 动画对象会在指定的时间里 (duration). 依次显示values 数组中的每一个关键帧
    keyframe.values = @[v1,v2,v3,v4,v5];
    keyframe.duration = 10;
    // 每一帧的时间,  每一帧的时间为比例的累加计算  取值范围 0-1,没有设置的话 每一帧的时间是平分的
    keyframe.keyTimes = @[@0.1,@0.1,@0.1,@0.1];
   [self.MyLabel.layer addAnimation:keyframe forKey:@"系统保留关键字"];



iOS 自动布局动画_动画效果_07


关键帧动画的演示



--------- CAAnimationGroup 动画组--------

// 创建
CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = 10;
// 把上面两个动画加到这个动画组里面
group.animations = @[basic,keyframe];
[self.MyLabel.layer addAnimation:group forKey:@"同上"];

--------------- CASpringAnimation 模拟弹簧动画效果--------

// 创建一个弹簧动画   结构关键字段  意思是竖直方向上  模拟弹簧  
CASpringAnimation *spring  = [CASpringAnimation animationWithKeyPath:@"position.y"];
    // 设置动画效果的初始值
    spring.fromValue = @50;
    // 设置动画的结束值
    spring.toValue = @10;
    // 阻尼系数
    spring.damping = 0.1;
    // 刚度系数: (劲度系数 / 弹性系数): 系数越大,形变的产生的力越大, 运动越快
    spring.stiffness = 10;
   // 质量: 影响图层运动时候的惯性, 质量越大弹簧拉伸和压缩的幅度越大 (动画的幅度,波动变大)
    spring.mass = 1;
    // 初识速率: 动画视图的初识速度大小
    // 速率为正时候, 速度方向与运动方向一致, 否则相仿.
    spring.initialVelocity = 1;
    // settlingDuration 结算时间,预估弹簧动画到停住的时间的估算, 根据当前动画的各个参数估算, 通常弹簧动画的估算时间使用结算时间比较准确
    spring.duration = spring.settlingDuration;
  [self.MyLabel.layer addAnimation:spring forKey:@"弹簧"];



iOS 自动布局动画_iOS 自动布局动画_08


弹簧效果动画



---------- CATransition -------

// 创建
CATransition *trans = [CATransition animation];
  // 效果
  trans.type = @"pageCurl";
  // 开始位置 (0-1)
  trans.startProgress = 0;
  // 结束位置 (0-1)
  trans.endProgress = 1;
  // 效果方向
  trans.subtype = kCATransitionFromLeft;
   // 重复次数
  trans.repeatCount = 10;
  // 持续时间
  trans.duration = 3;
   [self.MyView.layer addAnimation:trans forKey:@"11"];



iOS 自动布局动画_图层_09


 


iOS 自动布局动画_动画效果_10