三、设置图层对象
图层对象是Core Animation的核心。图层管理APP的可是内容,并提供修改内容的style和外观的方法。
1、改变UIView使用的layer类
我们可以通过复写view的layerClass方法返回一个不同的类对象,来改变view的层的类型。大多数视图都默认创建了CALayer对象,并使用这个层对象来存储其内容。对于大多数view,默认的就是最好的,不必再更改。但是有时候在某些情况下,其他不同的层类可能会更合适。比如说,我们也许会在下面的情况中更改类:
-
view使用Metal或OpenGL ES绘制内容,这种情况下,我们应该使用 CAMetalLayer 或者 CAEAGLLayer 层对象,会更合适。
-
能提供更好的性能的特殊的层类;
-
利用特殊的Core Animation层类,如粒子发射器或复制器。
更改view的layer类非常简单,如下表所示,我们只需要复写layerClass方法,并返回我们想使用的类对象。在展示之前,view就要调用layerClass方法,并使用返回值来为自己创建新的layer对象。一旦创建了,view的layer对象就不能更改了。
+ (Class) layerClass {
return [CAMetalLayer class];
}
2、改变NSView使用的layer类
通过复写 makeBackingLayer 方法来更改NSView使用的layer类。在方法的实现中,创建并返回想使用的层对象。我们可以在想使用自定义的层,如可滚动的或者绑定的层时,复写这个方法。
3、不同的layer类提供的特殊行为
Core Animation定义了许多标准layer类。每个layer类都为一种特殊使用情况而定义。 CALayer类是所有layer类的根类。它定义了所有layer对象必须支持的行为,也是view使用的默认类型。然而,我们也可以指定下表中的layer类之一。
Class | Usage |
---|---|
CAEmitterLayer | 用于实现基于Core Animation的粒子提交系统。emitter layer对象控制粒子的产生及其起源。 |
CAGradientLayer | 用于绘制颜色梯度,颜色梯度可填充layer的形状(在圆角区域内) |
CAMetalLayer | 用于设置和修复drawable纹理,以使用metal呈现layer内容。 |
CAEAGLLayer | 用于设置backing store和上下文环境以使用 OpenGL ES来渲染层内容。 |
CAReplicatorLayer | 当我们想自动复制一个或多个子层时使用。replicator为我们制作副本并使用指定properties来改变副本的外观和属性 |
CAScrollLayer | 用于管理由多个子层组成的可滚动区域 |
CAShapeLayer | 用于绘制三次贝塞尔曲线。Shape layers对于绘制基于路径的形状非常有利,因为它总是可以产生一个清晰的路径,而不是绘制到层的backing store中的路径。清晰的结果涉及到在主线程中渲染形状和缓存结果。 |
CATextLayer | 用于呈现普通的字符串或者带属性的字符串 |
CATiledLayer | 用于管理可以分割成小片并支持内容的缩放的独立呈现的的大图片 |
CATransformLayer | 用于渲染真实的3D层级体系,而不是其他layer类实现的扁平化层级体系 |
QCCompositionLayer | 仅支持OSX |
4、提供层的内容
层时管理APP提供的内容的数据对象。一个层的内容,由包含展示的可视数据的bitmap组成。我们可以以下面三种方式之一为bitmap提供内容:
-
直接给layer对象的contents属性指定一个image对象。(这种方式最适用于不怎么更改的层内容。)
-
给layer设置一个delegate对象,并让delegate绘制层的内容。(这种方式最适用于周期性变换,并且由外部对象提供的layer内容,比如view。)
-
定义layer的子类,并复写绘制方式之一来自己提供layer内容。(如果我们必须创建自定义的layer子类,或者如果我们想更改layer的基础绘制行为,这种方式最适合。)
-
使用image为layer内容
给layer的content属性直接分配一个image。这个image的属性必须是 CGImageRef 属性。图片的分辨率要和本地的分辨率匹配。
在多个地方使用相同image的情况下,这种方式可以节约内存。
-
使用delegate提供layer的内容
如果layer的内容是动态改变的,我们可以使用delegate对象来提供和更新所需内容。在展示时,layer调用delegate的方法来提供所需内容:
1、如果delegate实现了 [displayLayer:]方法,这个实现就负责创建bitmap,并分配给layer的contents属性;
2、如果delegate实现了 [drawLayer:inContext:]方法,Core Animation会创建bitmap,创建一个图形上下文来绘制bitmap,然后调用delegate方法来填充bitmap。delegate所有的方法要做的就是绘制到图形上下文中。
delegate必须有实现[displayLayer:]方法或 [drawLayer:inContext:]方法。如果delegate这两个方法都实现了,layer就只调用[displayLayer:]方法。
-
通过子类来提供层内容
当定义子类时,我们可以使用下面方式之一来绘制层的内容:
复写layer的 display方法,并使用这个方法直接来设置layer的contents属性;
复写layer的 [drawInContext:]方法,并使用这个方法来在所提供的图形上下文环境中绘制;
复写哪个方法取决于我们需要控制多少绘制进程。
5、调整layer的可视style和外观
除了基于图片的contents外,layer还有填充的背景,和描边。填充的背景色呈现在layer的后面,边框呈现在图像的顶部。如图所示,如果图层包含子层,子层也会展示在边框下面。因为背景色位于图片之后,颜色会透过图片的透明部分。
image.png给layer添加边框和背景色
设置layer的背景色和边框
myLayer.backgroundColor = [NSColor greenColor].CGColor;
myLayer.borderColor = [NSColor blackColor].CGColor;
myLayer.borderWidth = 3.0;
6、层支持圆角半径 Corner Radius
[cornerRadius]属性来设置层的圆角。Corner Radius不会影响layer的contents属性设置的image,除非 [masksToBounds]属性被设置为YES。但是,Corner Radius会一直影响层的背景色和边框的绘制。
image.png层的圆角
7、层支持内置阴影
阴影通过使它看起来像漂浮在底层内容之上,从而增加了层的深度。阴影的opacity默认是0,更改这个值会使Core Animation绘制阴影。因为阴影默认是直接放在层下的。
image.png给layer添加阴影
layer添加了阴影时,阴影就是content的一部分,但是往往引用会向外延伸bounds的区域。如果启用layer的这个 [masksToBounds] 属性,边缘周围的阴影效果会被裁剪。 如果图层包含了任何透明的内容,这可能会导致一个奇怪的效果,那就是图层下面的阴影部分仍然可见,而图层之外的部分则不可见。
如果你想要一个阴影但又想要使用边界mask,那就使用两个层。将mask应用到包含内容的层中,然后将该层嵌入到启用阴影效果的大小完全相同的第二层中。
8、给layer添加自定义的属性
CAAnimation和CALayer类扩展了键值编码约定来支持自定义属性。我们可以使用这种方式向层添加数据,并使用我们定义的自定义key检索数据。甚至可以将操作与自定义属性关联起来,这样当您更改属性时,就会执行相应的动画。
四、动画图层内容
Core Animation提供的基础架构使我们可以很容易的为应用程序的图层创建复杂的动画,并且扩展到任何拥有这些图层的视图。例如改变一个图层的frame矩形的大小,改变它在屏幕上的位置,应用旋转变换,或者改变它的不透明度。使用Core Animation,初始化一个动画通常就像改变属性一样简单,但是你也可以创建动画并显式设置动画参数。
1、动画图层属性的简单更改
2、关键帧动画比基础动画的时间和步调更加复杂。
3、显示动画可以移除,但是隐式动画不能移除。
五、构建图层的体系
iOS中的view都是支持layer的。所以构建层的结构不是很重要。
1、添加层到层级体系中
图层的层级体系在很多方面和视图的层级体系很像。我们可以嵌套层到另一个层中,来创建层的父子关系。但是这种父子关系会影响子层的各个方面。比如说,子层的内容会位于父类之上,子层的位置和父层的坐标系统有关,父层上的变换会影响子层。
1.1、添加、插入、移除子层
添加
addSublayer:
插入
insertSublayer:above:
insertSublayer:atIndex:
insertSublayer:below:
移除
removeFromSuperlayer
替换
replaceSublayer:with:
1.2、部署和缩放子层
应该养成在创建层的时候设置层的位置和尺寸的习惯。
myLayer.bounds = CGRectMake(0, 0, 100, 100);
myLayer.position = CGPointMake(200, 200);
position和锚点相关。
1.3、层级关系如何影响动画
父层的某些属性会影响其子层的动画行为。这样的属性之一就是speed属性,会加速动画的速度。默认speed属性值为1,当修改为2时,会使动画两倍原来的速度,从而以一半的时间就完成了。这个属性影响的不仅仅是自己这一层,还有其子层。这些变化也是倍增的。如果子层和其父层的speed都是2.0,那么子层的动画就是原始speed的四倍。
大多数层的改变都会以可预测的方式影响着其包含的子层。比如说,对层应用旋转变换,就会旋转该层及其子层。相似地,改变层的opacity,就会改变子层的opacity。改变层的尺寸,则遵循下面的“调整层级体系的布局”中的布局规则。
网友评论