iOS-25-iOS-Core-Animation-Advanced-Techniques图层的树状结构

<blockquote>
<p>巨妖有图层,洋葱也有图层,你有吗?我们都有图层 -- 史莱克</p>
</blockquote>

<p>Core Animation其实是一个令人误解的命名。你可能认为它只是用来做动画的,但实际上它是从一个叫做<em>Layer Kit</em>这么一个不怎么和动画有关的名字演变而来,所以做动画这只是Core Animation特性的冰山一角。</p>

<p>Core Animation是一个<em>复合引擎</em>,它的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的<em>图层</em>,存储在一个叫做<em>图层树</em>的体系之中。于是这个树形成了<strong>UIKit</strong>以及在iOS应用程序当中你所能在屏幕上看见的一切的基础。</p>

<p>在我们讨论动画之前,我们将从图层树开始,涉及一下Core Animation的<em>静态</em>组合以及布局特性。</p>

<h2>图层和视图</h2>

<p>如果你曾经在iOS或者Mac OS平台上写过应用程序,你可能会对<em>视图</em>的概念比较熟悉。一个视图就是在屏幕上显示的一个矩形块(比如图片,文字或者视频),它能够拦截类似于鼠标点击或者触摸手势等用户输入。视图在层级关系中可以互相嵌套,一个视图可以管理它的所有子视图的位置。图1.1显示了一种典型的视图层级关系</p>

图1.1

<p>图1.1 一种典型的iOS屏幕(左边)和形成视图的层级关系(右边)</p>

<p>在iOS当中,所有的视图都从一个叫做<code>UIVIew</code>的基类派生而来,<code>UIView</code>可以处理触摸事件,可以支持基于<em>Core Graphics</em>绘图,可以做仿射变换(例如旋转或者缩放),或者简单的类似于滑动或者渐变的动画。</p>

<h3>CALayer</h3>

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

<p><code>CALayer</code>并不清楚具体的<em>响应链</em>(iOS通过视图层级关系用来传送触摸事件的机制),于是它并不能够响应事件,即使它提供了一些方法来判断是否一个触点在图层的范围之内(具体见第三章,“图层的几何学”)</p>

<h3>平行的层级关系</h3>

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

图1.2

<p>图1.2 图层的树状结构(左边)以及对应的视图层级(右边)</p>

<p>实际上这些背后关联的图层才是真正用来在屏幕上显示和做动画,<code>UIView</code>仅仅是对它的一个封装,提供了一些iOS类似于处理触摸的具体功能,以及Core Animation底层方法的高级接口。</p>

<p>但是为什么iOS要基于<code>UIView</code>和<code>CALayer</code>提供两个平行的层级关系呢?为什么不用
一个简单的层级来处理所有事情呢?原因在于要做职责分离,这样也能避免很多重复代码。在iOS和Mac
OS两个平台上,事件和用户交互有很多地方的不同,基于多点触控的用户界面和基于鼠标键盘有着本质的区别,这就是为什么iOS有UIKit和<code>UIView</code>,但是Mac OS有AppKit和<code>NSView</code>的原因。他们功能上很相似,但是在实现上有着显著的区别。</p>

<p>绘图,布局和动画,相比之下就是类似Mac笔记本和桌面系列一样应用于iPhone和iPad触屏的概念。把这种功能的逻辑分开并应用到独立的
Core Animation框架,苹果就能够在iOS和Mac
OS之间共享代码,使得对苹果自己的OS开发团队和第三方开发者去开发两个平台的应用更加便捷。</p>

<p>实际上,这里并不是两个层级关系,而是四个,每一个都扮演不同的角色,除了视图层级和图层树之外,还存在<em>呈现树</em>和<em>渲染树</em>,将在第七章“隐式动画”和第十二章“性能调优”分别讨论。</p>

<h2></a>图层的能力</h2>

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

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

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

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

<ul>
<li>阴影,圆角,带颜色的边框</li>
<li>3D变换</li>
<li>非矩形范围</li>
<li>透明遮罩</li>
<li>多级非线性动画</li>
</ul>

<p>我们将会在后续章节中探索这些功能,首先我们要关注一下在应用程序当中<code>CALayer</code>是怎样被利用起来的。</p>

<h2>使用图层</h2>

<p>首先我们来创建一个简单的项目,来操纵一些<code>layer</code>的属性。打开Xcode,使用<em>Single View Application</em>模板创建一个工程。</p>

<p>在屏幕中央创建一个小视图(大约200 X 200的尺寸),当然你可以手工编码,或者使用Interface Builder(随你方便)。确保你的视图控制器要添加一个视图的属性以便可以直接访问它。我们把它称作<code>layerView</code>。</p>

<p>运行项目,应该能在浅灰色屏幕背景中看见一个白色方块(图1.3),如果没看见,可能需要调整一下背景window或者view的颜色</p>

<p></p>


图1.3

<p>图1.3 灰色背景上的一个白色<code>UIView</code></p>

<p>这并没有什么令人激动的地方,我们来添加一个色块,在白色方块中间添加一个小的蓝色块。</p>

<p>我们当然可以简单地在已经存在的<code>UIView</code>上添加一个子视图(随意用代码或者IB),但这不能真正学到任何关于图层的东西。</p>

<p>于是我们来创建一个<code>CALayer</code>,并且把它作为我们视图相关图层的子图层。尽管<code>UIView</code>类
的接口中暴露了图层属性,但是标准的Xcode项目模板并没有包含Core
Animation相关头文件。所以如果我们不给项目添加合适的库,是不能够使用任何图层相关的方法或者访问它的属性。所以首先需要添加
QuartzCore框架到Build Phases标签(图1.4),然后在vc的.m文件中引入库。</p>

图1.4

<p>图1.4 把QuartzCore库添加到项目</p>

<p>之后就可以在代码中直接引用<code>CALayer</code>的属性和方法。在清单1.1中,我们用创建了一个<code>CALayer</code>,设置了它的<code>backgroundColor</code>属性,然后添加到<code>layerView</code>背后相关图层的子图层(这段代码的前提是通过IB创建了<code>layerView</code>并做好了连接),图1.5显示了结果。</p>

<p>清单1.1 给视图添加一个蓝色子图层</p>

  #import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //create sublayer
    CALayer *blueLayer = [CALayer layer];
    blueLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
    blueLayer.backgroundColor = [UIColor blueColor].CGColor;
    //add it to our view
    [self.layerView.layer addSublayer:blueLayer];
}
@end
图1.5

<p>图1.5 白色<code>UIView</code>内部嵌套的蓝色<code>CALayer</code></p>

<p>一个视图只有一个相关联的图层(自动创建),同时它也可以支持添加无数多个子图层,从清单1.1可以看出,你可以显示创建一个单独的图层,并且把它
直接添加到视图关联图层的子图层。尽管可以这样添加图层,但往往我们只是见简单地处理视图,他们关联的图层并不需要额外地手动添加子图层。</p>

<p>在Mac OS平台,10.8版本之前,一个显著的性能缺陷就是由于用了视图层级而不是单独在一个视图内使用<code>CALayer</code>树状层级。但是在iOS平台,使用轻量级的<code>UIView</code>类并没有显著的性能影响(当然在Mac OS 10.8之后,<code>NSView</code>的性能同样也得到很大程度的提高)。</p>

<p>使用图层关联的视图而不是<code>CALayer</code>的好处在于,你能在使用所有<code>CALayer</code>底层特性的同时,也可以使用<code>UIView</code>的高级API(比如自动排版,布局和事件处理)。</p>

<p>然而,当满足以下条件的时候,你可能更需要使用<code>CALayer</code>而不是<code>UIView</code></p>

<ul>
<li>开发同时可以在Mac OS上运行的跨平台应用</li>
<li>使用多种<code>CALayer</code>的子类(见第六章,“特殊的图层“),并且不想创建额外的<code>UIView</code>去包封装它们所有</li>
<li>做一些对性能特别挑剔的工作,比如对<code>UIView</code>一些可忽略不计的操作都会引起显著的不同(尽管如此,你可能会直接想使用OpenGL绘图)</li>
</ul>

<p>但是这些例子都很少见,总的来说,处理视图会比单独处理图层更加方便。</p>

<h2>总结</h2>

<p>这一章阐述了图层的树状结构,说明了如何在iOS中由<code>UIView</code>的层级关系形成的一种平行的<code>CALayer</code>层级关系,在后面的实验中,我们创建了自己的<code>CALayer</code>,并把它添加到图层树中。</p>

<p>在第二章,“图层关联的图片”,我们将要研究一下<code>CALayer</code>关联的图片,以及Core Animation提供的操作显示的一些特性。</p>

原文链接:https://github.com/AttackOnDobby/iOS-Core-Animation-Advanced-Techniques

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容