Core Animation 是在iOS上负责一般UI绘图和动画的框架。
真的要详细介绍Core Animation,都可以写一本书,我们这边尽量简短介绍。Core Animation大概分成3种主要的class;
CALayer
CAAnimation
CATransaction
1. CALayer与UIView的关系
任何一个view都有2种性质组成的,可以操作和可以被看到。
在iOS上,UIView的外观呈现都是由Core Animation实现。我们看到的UIView的样子,其实是里头CALayer的样子.
在iOS上,我们可以使用一系列的UIView的class method产生动画,比如 +animateWithDuration:delay:options:animations:completion:,其实并不是view本身产生动画,而是view里头的CALayer的功劳。
如果我们要改变一个View的外观,可以通过在UIView的subclass中覆盖掉 drawRect:方法。
drawRect: 其实是个delegate call,用途不是绘制View,而是绘制CALayer的内容。
每个UIView都是属于自己专属CALayer的delegate,当我们要重绘某个view的内容时,其实是叫CALayer重绘。
另外,CALayer 并不是 responder。当我们遇到很复杂的画面,有许多不同的元素一直变化、移动的时候,我们不妨考虑让App中出现许多layer,而不是view。因为每多一个view就会在 responder chain当做多一个responder,会影响每一轮run loop的速度。一个layer上面可以继续添加layer,就像view可以addSubview:,CALayer也有对应的 addSublayer:方法。
最重要的,如果你自己建立的CALayer,千万不要把delegate指到某个UIView上,UIView已经是自己的layer的delegate了。
2. 画面截图
在iOS 7之前,我们利用view的内容是由layer绘制这点,产生某个view截图。
只要求某个view的layer在对某个graphic context,然后把绘制的内容放进一个UIImage里即可。
真的要详细介绍Core Animation,都可以写一本书,我们这边尽量简短介绍。Core Animation大概分成3种主要的class;
CALayer
CAAnimation
CATransaction
1. CALayer与UIView的关系
任何一个view都有2种性质组成的,可以操作和可以被看到。
在iOS上,UIView的外观呈现都是由Core Animation实现。我们看到的UIView的样子,其实是里头CALayer的样子.
在iOS上,我们可以使用一系列的UIView的class method产生动画,比如 +animateWithDuration:delay:options:animations:completion:,其实并不是view本身产生动画,而是view里头的CALayer的功劳。
如果我们要改变一个View的外观,可以通过在UIView的subclass中覆盖掉 drawRect:方法。
drawRect: 其实是个delegate call,用途不是绘制View,而是绘制CALayer的内容。
每个UIView都是属于自己专属CALayer的delegate,当我们要重绘某个view的内容时,其实是叫CALayer重绘。
另外,CALayer 并不是 responder。当我们遇到很复杂的画面,有许多不同的元素一直变化、移动的时候,我们不妨考虑让App中出现许多layer,而不是view。因为每多一个view就会在 responder chain当做多一个responder,会影响每一轮run loop的速度。一个layer上面可以继续添加layer,就像view可以addSubview:,CALayer也有对应的 addSublayer:方法。
最重要的,如果你自己建立的CALayer,千万不要把delegate指到某个UIView上,UIView已经是自己的layer的delegate了。
2. 画面截图
在iOS 7之前,我们利用view的内容是由layer绘制这点,产生某个view截图。
只要求某个view的layer在对某个graphic context,然后把绘制的内容放进一个UIImage里即可。
@implementation UIView(MyExtensions)
- (UIImage *)imageOfCurrentContent
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size,YES,[UIScreen mainScreen].scale);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
产生画面截图这点在制作很多UI时非常有用,像我们想要某个view A变形、然后另一个view B出现这样的专场效果,中间的变化就可以对A于B的截图做相关处理,比起直接改变2个view,让view不断重绘,处理2张图片的速度会快很多。设计UI是经常需要许多障眼法。
iOS7之后可以使用新的API, drawViewHierarchyInRect:afterScreenUpdates:
3. 设置 CALayer 的基本样式和属性
CALayer有一些UIView没有的属性,比如 cornerRadius、borderWidth、borderColor,我可以设置layer的边框和颜色。
shadowOpacity、shadowRadius、shadowOffset、shadowColor 用来设置阴影的颜色、位置、尺寸大小等。建议另外设置 shadowPaht,用一个 CGPath 描述阴影的外框范围。
因为改变Layer属性会产生动画效果,所以当我们建立好layer之后,会先设定好frame,才把layer加到super layer上,不然如果先加到super layer,才去改变frame,就会产生很奇怪的动画效果。
CALayer预设都是一倍解析度,所以需要告诉CALayer应该用怎样的解析度,方法是通过设定 contentsScale 属性。
layer.contentsScale = [UIScreen mainScreen].scale;