美文网首页
Core Animation

Core Animation

作者: LuckyZong | 来源:发表于2018-03-14 09:51 被阅读0次

    图层与视图

    一个视图就是在屏幕上显示的一个矩形块(比如图片,文字或者视频),它能够拦截类似于鼠标点击或者触摸手势等用户输入。视图在层级关系中可以互相嵌套,一个视图可以管理它的所有子视图的位置。

    CALayer

    CALayer 类在概念上和 UIView 类似,同样也是一些被层级关系树管理的矩形块,同样也可以包含一些内容(像图片,文本或者背景色),管理子图层的位置。它们有一些方法和属性用来做动画和变换。和 UIView 最大的不同是 CALayer 不处理用户的交互。

    CALayer 并不清楚具体的响应链(iOS通过视图层级关系用来传送触摸事件的机制),于是它并不能够响应事件,即使它提供了一些方法来判断是否一个触点在图层的范围之内。

    平行的层级关系

    每一个 UIview 都有一个 CALayer 实例的图层属性,也就是所谓的backinglayer,视图的职责就是创建并管理这个图层,以确保当子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作

    图层的能力

    如果说 CALayer 是 UIView 内部实现细节,那我们为什么要全面地了解它呢?苹果当然为我们提供了优美简洁的 UIView 接口,那么我们是否就没必要直接去处理Core Animation的细节了呢?

    某种意义上说的确是这样,对一些简单的需求来说,我们确实没必要处理 CALayer ,因为苹果已经通过 UIView 的高级API间接地使得动画变得很简单。

    但是这种简单会不可避免地带来一些灵活上的缺陷。如果你略微想在底层做一些改变,或者使用一些苹果没有在 UIView 上实现的接口功能,这时除了介入CoreAnimation底层之外别无选择。

    我们已经证实了图层不能像视图那样处理触摸事件,那么他能做哪些视图不能做的呢?这里有一些 UIView 没有暴露出来的CALayer的功能:

    阴影,圆角,带颜色的边框

    3D变换

    非矩形范围

    透明遮罩

    多级非线性动画


    寄宿图

    contents属性

    CALayer 有一个属性叫做 contents ,这个属性的类型被定义为id,意味着它可以是任何类型的对象。在这种情况下,你可以给 contents 属性赋任何值,你的app仍然能够编译通过。但是,在实践中,如果你给 contents 赋的不是CGImage,那么你得到的图层将是空白的。

    contents 这个奇怪的表现是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。如果你试图在iOS平台上将UIImage的值赋给它,只能得到一个空白的图层。

    一些初识Core Animation的iOS开发者可能会对这个感到困惑。头疼的不仅仅是我们刚才提到的这个问题。事实上,你真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针。UIImage有一个CGImage属性,它返回一个"CGImageRef",如果你想把这个值直接赋值给CALayer的 contents ,那你将会得到一个编译错误。因为CGImageRef并不是一个真正的Cocoa对象,而是一个Core Foundation类型。

    尽管Core Foundation类型跟Cocoa对象在运行时貌似很像(被称作toll-freebridging),他们并不是类型兼容的,不过你可以通过bridged关键字转换。如果要给图层的寄宿图赋值,你可以按照以下这个方法:

    layer.contents = (__bridge id)image.CGImage;

    如果你没有使用ARC(自动引用计数),你就不需要__bridge这部分。但是,你干嘛不用ARC?!

    contentGravity

    CALayer与 contentMode 对应的属性叫做 contentsGravity ,但是它是一个NSString类型,而不是像对应的UIKit部分,那里面的值是枚举。 contentsGravity 可选的常量值有以下一些:

    kCAGravityCenter

    kCAGravityTop

    kCAGravityBottom

    kCAGravityLeft

    kCAGravityRight

    kCAGravityTopLeft

    kCAGravityTopRight

    kCAGravityBottomLeft

    kCAGravityBottomRight

    kCAGravityResize

    kCAGravityResizeAspect

    kCAGravityResizeAspectFill

    和 cotentMode 一样, contentsGravity 的目的是为了决定内容在图层的边界

    中怎么对齐,我们将使用kCAGravityResizeAspect,它的效果等同于

    UIViewContentModeScaleAspectFit, 同时它还能在图层中等比例拉伸以适应图层

    的边界。

    self.layerView.layer.contentsGravity = kCAGravityResizeAspect;

    maskToBounds

    UIView有一个叫做 clipsToBounds 的属性可以用来决定是否显示超出边界的内容,CALayer对应的属性叫做 masksToBounds

    contentsRect

    CALayer的 contentsRect 属性允许我们在图层边框里显示寄宿图的一个子域。这涉及到图片是如何显示和拉伸的,所以要比 contentsGravity 灵活多了和 bounds , frame 不同, contentsRect 不是按点来计算的,它使用了单位坐标,单位坐标指定在0到1之间,是一个相对值(像素和点就是绝对值)。所以他们是相对与寄宿图的尺寸的。iOS使用了以下的坐标系统:

    点 —— 在iOS和Mac OS中最常见的坐标体系。点就像是虚拟的像素,也被称作逻辑像素。在标准设备上,一个点就是一个像素,但是在Retina设备上,一个点等于2*2个像素。iOS用点作为屏幕的坐标测算体系就是为了在Retina设备和普通设备上能有一致的视觉效果。

    像素 —— 物理像素坐标并不会用来屏幕布局,但是仍然与图片有相对关系。UIImage是一个屏幕分辨率解决方案,所以指定点来度量大小。但是一些底层的图片表示如CGImage就会使用像素,所以你要清楚在Retina设备和普通设备上,他们表现出来了不同的大小。

    单位 —— 对于与图片大小或是图层边界相关的显示,单位坐标是一个方便的度量方式, 当大小改变的时候,也不需要再次调整。单位坐标在OpenGL这种纹理坐标系统中用得很多,Core Animation中也用到了单位坐标。

    相关文章

      网友评论

          本文标题:Core Animation

          本文链接:https://www.haomeiwen.com/subject/zgcznxtx.html