iOS

iOS核心动画高级技巧Tips

iOS核心动画重点摘要

Posted by 袁平 on April 29, 2019

前言

iOS核心动画高级技巧摘要


正文


一. 图层树

  1. 和UIView最大的不同是CALayer不处理用户的交互;CALayer并不清楚具体的响应链,即使它提供了一些方法来判断是否一个触点在图层的范围之内

  2. 每一个UIview都有一个CALayer实例的图层属性

  3. UIView没有暴露出来的CALayer的功能:
    1. 阴影,圆角,带颜色的边框
    2. 3D变换
    3. 非矩形范围
    4. 透明遮罩
    5. 多级非线性动画
  4. 当满足以下条件的时候,你可能更需要使用CALayer而不是UIView:
    1. 开发同时可以在Mac OS上运行的跨平台应用
    2. 使用多种CALayer的子类(见第六章,“特殊的图层“),并且不想创建额外的UIView去包封装它们所有
    3. 做一些对性能特别挑剔的工作,比如对UIView一些可忽略不计的操作都会引起显著的不同(尽管如此,你可能会直接想使用OpenGL绘图)

二. 寄宿图

  1. 利用CALayer在一个普通的UIView中显示了一张图片。这不是一个UIImageView,它不是我们通常用来展示图片的方法
    UIImage *image = [UIImage imageNamed:@"Snowman.png"];
    //add it directly to our view's layer
    self.layerView.layer.contents = (__bridge id)image.CGImage;
    
  2. 如果你不需要寄宿图,那就不要重写drawRect方法,这会造成CPU资源和内存的浪费,这也是为什么苹果建议:如果没有自定义绘制的任务就不要在子类中写一个空的-drawRect:方法(因为如果UIView检测到-drawRect: 方法被调用了,它就会为视图分配一个寄宿图,这个寄宿图的像素尺寸等于视图大小乘以 contentsScale的值)

三. 图层几何学

  1. UIView有三个比较重要的布局属性:frame,bounds和center,CALayer对应地叫做frame,bounds和position。为了能清楚区分,图层用了“position”,视图用了“center”,但是他们都代表同样的值(frame代表了图层的外部坐标(也就是在父图层上占据的空间),bounds是内部坐标({0, 0}通常是图层的左上角),center和position都代表了相对于父图层anchorPoint所在的位置)

  2. 视图的frame,bounds和center属性仅仅是存取方法,当操纵视图的frame,实际上是在改变位于视图下方CALayer的frame,不能够独立于图层之外改变视图的frame

  3. 对于视图或者图层来说,frame并不是一个非常清晰的属性,它其实是一个虚拟属性,是根据bounds,position和transform计算而来,所以当其中任何一个值发生改变,frame都会变化。相反,改变frame的值同样会影响到他们当中的值

  4. 当旋转时frame属性和bounds的宽高不再一致

iOS_Animation

  1. 认来说,anchorPoint位于图层的中点;视图的anchorPoint没有暴露,但是图层的anchorPoint可以被移动;比如你可以把它置于图层frame的左上角

  1. CALayer还有另外两个属性,zPosition和anchorPointZ,二者都是在Z轴上描述图层位置的浮点类型

  2. CALayer并不关心任何响应链事件,所以不能直接处理触摸事件或者手势。但是它有一系列的方法帮你处理事件:-containsPoint:和-hitTest:

    1. -containsPoint:接受一个在本图层坐标系下的CGPoint,如果这个点在图层frame范围内就返回YES
    2. -hitTest:方法同样接受一个CGPoint类型参数,而不是BOOL类型,它返回图层本身,或者包含这个坐标点的叶子节点图层。这意味着不再需要像使用-containsPoint:那样,人工地在每个子图层变换或者测试点击的坐标。如果这个点在最外面图层的范围之外,则返回nil(注意当调用图层的-hitTest:方法时,测算的顺序严格依赖于图层树当中的图层顺序(和UIView处理事件类似)。之前提到的zPosition属性可以明显改变屏幕上图层的顺序,但不能改变事件传递的顺序)

四. 视觉效果