圖層樹
先來介紹幾個(gè)我們常見的名詞:
Core Animation:只看它的名字會(huì)讓人產(chǎn)生一種誤解——核心動(dòng)畫渗勘。從功能方面來看這并不能體現(xiàn)他的強(qiáng)大之處通铲,Core Animation 是從一個(gè)Layer Kit 的庫(kù)演變而來的(當(dāng)然 Layer Kit 這個(gè)名字就不會(huì)讓我們直接聯(lián)想到動(dòng)畫相關(guān)了),動(dòng)畫對(duì) Core Animation 來說只是其中的一部分糕珊。
Core Animation 是一個(gè)復(fù)合引擎尤蒿,它的職責(zé)就是盡可能快的組合屏幕上不同的可視內(nèi)容必逆,這個(gè)內(nèi)容是被分解成獨(dú)立的圖層吗氏,存儲(chǔ)在一個(gè)叫做圖層樹的體系之中芽偏。**于是這個(gè)樹形成了UIKit 和在ios應(yīng)用程序中你所能在屏幕上看見的一切內(nèi)容的基礎(chǔ)。
在開始核心動(dòng)畫之前弦讽,我們先從圖層樹開始污尉,了解一些 Core Animation 的靜態(tài)組合和“布局特性”。
圖層與視圖
視圖——UIView
如果你在ios應(yīng)用程序的開發(fā)經(jīng)驗(yàn)坦袍,對(duì)視圖概念應(yīng)該是比較熟悉十厢,一個(gè)視圖就是一個(gè)屏幕上顯示的矩形塊(比如圖片,視頻捂齐、文字)蛮放,同時(shí)它能夠攔截類似鼠標(biāo)點(diǎn)擊或者觸摸手勢(shì)等的用戶輸入。視圖在層級(jí)關(guān)系中可以互相嵌套奠宜,一個(gè)視圖可以管理它所有子視圖的位置包颁。
在 ios 中所有的視圖都是從 UIView 基類中派生出來的压真,UIView 可以處理觸摸事件娩嚼,可以支持基于 Core Graphics 的繪制,可以做仿射變換(例如旋轉(zhuǎn)或者縮放)滴肿,或者簡(jiǎn)單的類似于滑動(dòng)(frame)或者漸變(alpha)的動(dòng)畫岳悟。
圖層——CALayer
CALayer 和 UIView 在概念上類似,同樣也是一些被層級(jí)關(guān)系樹管理的矩形塊泼差,同樣也包含一些內(nèi)容(比如圖片贵少,文字,背景色)堆缘,同樣它也管理他所有的子圖層的位置滔灶,它們也有一些方法和屬性用來做動(dòng)畫和變換。 和 UIView 最大的不同是:CALayer 不處理用戶的交互(類似鼠標(biāo)點(diǎn)擊吼肥,觸摸手勢(shì))
CALayer 并不清楚具體的響應(yīng)鏈(ios 通過視圖層級(jí)關(guān)系用來傳遞觸摸事件的機(jī)制)录平,所以它并不能夠響應(yīng)事件,即使他提供了一些方法來判斷是否一個(gè)觸點(diǎn)在圖層范圍之內(nèi)(后文有介紹)缀皱。
平行的層級(jí)關(guān)系
每一個(gè) UIView 都有一個(gè) CALayer 類型的圖層屬性斗这。也就是所謂的 backing layer(永久層),視圖的職責(zé)就是創(chuàng)建并管理這個(gè)圖層啤斗,以確保子視圖在層級(jí)關(guān)系中添加或者刪除的時(shí)候表箭,他們關(guān)聯(lián)的圖層也同樣對(duì)應(yīng)在層級(jí)關(guān)系樹中有相同的操作
實(shí)際上這些背后關(guān)聯(lián)的圖層才是真正用來在屏幕上顯示和做動(dòng)畫的争占, UIView 僅僅是對(duì)它的一個(gè)封裝燃逻,提供了一些ios類似處理觸摸事件的一些具體功能。以及一些使用 Core Animation 底層方法的高級(jí)接口臂痕。
此時(shí)大家可能就有疑問:IOS為什么要基于 UIView 和 CALayer 提供兩套平行的層級(jí)關(guān)系呢伯襟?為什么不使用一個(gè)簡(jiǎn)單的層級(jí)來處理所有的事情?好問題握童,原因在于 要做職責(zé)分離姆怪,這樣也能避免很多重復(fù)代碼。在 ios 和 macOS 兩個(gè)平臺(tái)上澡绩,事件和用戶交互有很多地方的不同稽揭,基于多點(diǎn)觸控的用戶界面和基于鼠標(biāo)和鍵盤有著本質(zhì)的區(qū)別,這就是為什么ios有 UIKit 和 UIView , MacOS 有AppKit 和 NSView 肥卡。他們?cè)诠δ芎芟嗨葡疲窃趯?shí)現(xiàn)上有著顯著的區(qū)別。
繪圖步鉴、布局和動(dòng)畫相比之下就是類似Mac 筆記本和桌面系列一樣應(yīng)用于iPhone和iPad觸屏的概念揪胃。把兩個(gè)平臺(tái)上的這種功能的邏輯分開應(yīng)用到獨(dú)立的 Core Animation 框架,使得蘋果的OS團(tuán)隊(duì)和第三方開發(fā)者去開發(fā)兩個(gè)平臺(tái)的應(yīng)用更加便捷氛琢。
實(shí)際上喊递,這里并不是兩個(gè)層級(jí)關(guān)系,而是四個(gè)阳似,每一個(gè)都扮演不同的角色骚勘,除了視圖層級(jí)和圖層樹之外,還存在呈現(xiàn)樹和渲染樹撮奏,我們?cè)诤竺娴慕榻B俏讹。
圖層CALayer的能力
如果說 CALayer 是 UIView 的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),那 我們?yōu)槭裁催€要費(fèi)勁心思的了解他呢挽荡?當(dāng)然蘋果位我們提供了優(yōu)美簡(jiǎn)潔的 UIView 的接口藐石,那么我們是否就沒有必要直接去處理 Core Animation 一些實(shí)現(xiàn)上的細(xì)節(jié)了呢?
在某種程度是確實(shí)是這樣定拟,對(duì)一些簡(jiǎn)單的需求來說于微,我們確實(shí)沒有必要處理 CALayer , 蘋果已經(jīng)通過UIView 的高級(jí)API間接地使得動(dòng)畫變得很簡(jiǎn)單。
但是這種簡(jiǎn)單不可避免的會(huì)帶來靈活上的一些缺陷青自、如果你略微想在底層做一些改變株依,或是想要使用一些蘋果沒有在 UIView 中實(shí)現(xiàn)的接口功能,這時(shí)候處了介入Core Animation底層之外 別無(wú)其他選擇延窜。
我們已經(jīng)證實(shí)了圖層不能像視圖那樣處理觸摸時(shí)間恋腕,那它能做那些視圖不能做的呢?舉例一些 UIView 沒有暴露出的 CALayer 功能逆瑞。
- 圓角荠藤,陰影伙单,帶顏色的邊框
- 3D的動(dòng)畫變換
- 非舉行范圍繪制然眼。
- 透明遮罩
- 多級(jí)非線性動(dòng)畫
跟著我們學(xué)習(xí)的腳步衰絮,我們會(huì)一一為大家講解這些功能,但在此之前见间,我們首先要關(guān)注最基本的淤井,CALayer 是如何被使用的布疼。
使用圖層
我們使用代碼的形式進(jìn)行演示,
創(chuàng)建項(xiàng)目的代碼我們就省去了币狠,節(jié)約大家時(shí)間
項(xiàng)目創(chuàng)建完成
首先我們?cè)趧?chuàng)建一個(gè)子視圖(layerView)添加到 viewController 的視圖上游两。
效果如下:
然而這并沒有什么卵用,
我們想要在白色的視圖中添加一個(gè)藍(lán)色的區(qū)域漩绵,當(dāng)然你可以通過添加子視圖的方式實(shí)現(xiàn)贱案,但這對(duì)我們的學(xué)習(xí)layer沒有什么卵用。
因此我們通過創(chuàng)建圖層來完成渐行。于是呢我們創(chuàng)建一個(gè)layer圖層轰坊,并且把它作為我們視圖相關(guān)圖層的子圖層。盡管 UIView 的接口中暴露了圖層屬性祟印,但是標(biāo)準(zhǔn)的Xcode項(xiàng)目并包含Core Animation 的相關(guān)頭文件肴沫,所以如果我們不給項(xiàng)目添加合適的庫(kù),是不能使用任何圖層相關(guān)的方法或者訪問他的屬性的蕴忆。所以首先需要添加QuartzCore 框架到building phases下颤芬。
如圖所示:
之后就可以在代碼中應(yīng)用CALayer的屬性和方法了,我們創(chuàng)建一個(gè)Layer 設(shè)置藍(lán)色添加到layerView相關(guān)圖層的子圖層上套鹅,
代碼如下
UIView *layerView = [[UIView alloc] initWithFrame: CGRectMake(100, 100, 200, 200)];
layerView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:layerView];
//添加一個(gè)圖層
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(50, 50, 100, 100);
layer.backgroundColor = [UIColor blueColor].CGColor;
[layerView.layer addSublayer:layer];
咱們看效果:
一個(gè)視圖只有一個(gè)相關(guān)聯(lián)的圖層(自動(dòng)創(chuàng)建)站蝠,同時(shí)它也可以支持添加無(wú)數(shù)多個(gè)子圖層。從上面的例子我們可以看出卓鹿,你可以顯示創(chuàng)建一個(gè)單獨(dú)的圖層菱魔。并且把它直接添加到視圖關(guān)聯(lián)圖層的子圖層。盡管可以這樣添加圖層吟孙,但往往我們只是簡(jiǎn)單地處理視圖澜倦,他們關(guān)聯(lián)的圖層并不需要額外地手動(dòng)添加子視圖。
額外補(bǔ)充:
在 MacOS平臺(tái)杰妓,10.8版本之前藻治,一個(gè)顯著的性能缺陷就是 macOS 使用 UIView視圖層級(jí)而不在一個(gè)單獨(dú)的視圖內(nèi)使用CALayer樹狀層級(jí)。但在IOS平臺(tái)巷挥,使用輕量級(jí)的 UIView類并沒有顯著的性能影響(當(dāng)然在 MacOS 10.8系統(tǒng)之后桩卵,NSView 的性能有了很大的提升)
使用圖層關(guān)聯(lián)視圖層級(jí)而不是用CALayer的好處在于,你能在使用所有CALayer 底層特性的同時(shí),也可以使用UIView提供的高級(jí)API (比如雏节,自動(dòng)排版胜嗓、布局,響應(yīng)事件)
然而在以下場(chǎng)景钩乍,你可能更需要使用CALayer 兼蕊,而不用使用UIView
- 開發(fā)同時(shí)可以在Mac OS上運(yùn)行的跨平臺(tái)應(yīng)用。
- 使用多種 CALayer 的子類件蚕,并且不想創(chuàng)建額外的 UIView 去封裝他們。
- 做一些對(duì)性能特別挑剔的工作产禾,(比如對(duì) UIView 一些可忽略不計(jì)的操作都會(huì)引起性能方面顯著的不同排作,當(dāng)然,你也可以直接使用 openGL繪圖)亚情。
當(dāng)然這些場(chǎng)景比較少見妄痪,總體來說處理視圖還是比直接處理圖層方便一些。
文章總結(jié):
我們文中闡述了圖層的樹狀結(jié)構(gòu)楞件。說明了如何在ios中由 UIView 的層級(jí)關(guān)系形成的一種平行的CALayer層級(jí)關(guān)系衫生,后面使用Demo進(jìn)行了演示。
未完待續(xù)……