CoreAnimation之圖層樹

** 圖層的樹狀結(jié)構(gòu)**

Core Animation其實(shí)是一個(gè)令人誤解的命名。你可能認(rèn)為它只是用來做動(dòng)畫的,但實(shí)際上它是從一個(gè)叫做Layer Kit這么一個(gè)不怎么和動(dòng)畫有關(guān)的名字演變而來,所以做動(dòng)畫這只是Core Animation特性的冰山一角。
Core Animation是一個(gè)復(fù)合引擎,它的職責(zé)就是盡可能快地組合屏幕上不同的可視內(nèi)容,這個(gè)內(nèi)容是被分解成獨(dú)立的圖層,存儲(chǔ)在一個(gè)叫做圖層樹的體系之中。于是這個(gè)樹形成了UIKit以及在iOS應(yīng)用程序當(dāng)中你所能在屏幕上看見的一切的基礎(chǔ)。
在我們討論動(dòng)畫之前,我們將從圖層樹開始,涉及一下Core Animation的靜態(tài)組合以及布局特性。

圖層和視圖

如果你曾經(jīng)在iOS或者M(jìn)ac OS平臺(tái)上寫過應(yīng)用程序,你可能會(huì)對(duì)視圖的概念比較熟悉。一個(gè)視圖就是在屏幕上顯示的一個(gè)矩形塊(比如圖片,文字或者視頻),它能夠攔截類似于鼠標(biāo)點(diǎn)擊或者觸摸手勢(shì)等用戶輸入。視圖在層級(jí)關(guān)系中可以互相嵌套,一個(gè)視圖可以管理它的所有子視圖的位置。
在iOS當(dāng)中,所有的視圖都從一個(gè)叫做UIVIew的基類派生而來,UIView可以處理觸摸事件,可以支持基于CoreGraphics繪圖,可以做仿射變換(例如旋轉(zhuǎn)或者縮放),或者簡(jiǎn)單的類似于滑動(dòng)或者漸變的動(dòng)畫。

CALayer

CALayer類在概念上和UIView類似,同樣也是一些被層級(jí)關(guān)系樹管理的矩形塊,同樣也可以包含一些內(nèi)容(像圖片,文本或者背景色),管理子圖層的位置。它們有一些方法和屬性用來做動(dòng)畫和變換。和UIView最大的不同是CALayer不處理用戶的交互。
CALayer并不清楚具體的響應(yīng)鏈(iOS通過視圖層級(jí)關(guān)系用來傳送觸摸事件的機(jī)制),于是它并不能夠響應(yīng)事件,即使它提供了一些方法來判斷是否一個(gè)觸點(diǎn)在圖層的范圍之內(nèi)(具體見第三章,“圖層的幾何學(xué)”)

平行的層級(jí)關(guān)系

每一個(gè)UIview都有一個(gè)CALayer實(shí)例的圖層屬性,也就是所謂的backing layer,視圖的職責(zé)就是創(chuàng)建并管理這個(gè)圖層,以確保當(dāng)子視圖在層級(jí)關(guān)系中添加或者被移除的時(shí)候,他們關(guān)聯(lián)的圖層也同樣對(duì)應(yīng)在層級(jí)關(guān)系樹當(dāng)中有相同的操作,實(shí)際上這些背后關(guān)聯(lián)的圖層才是真正用來在屏幕上顯示和做動(dòng)畫,UIView僅僅是對(duì)它的一個(gè)封裝,提供了一些iOS類似于處理觸摸的具體功能,以及Core Animation底層方法的高級(jí)接口。

但是為什么iOS要基于UIView和CALayer提供兩個(gè)平行的層級(jí)關(guān)系呢?為什么不用一個(gè)簡(jiǎn)單的層級(jí)來處理所有事情呢?原因在于要做職責(zé)分離,這樣也能避免很多重復(fù)代碼。在iOS和Mac OS兩個(gè)平臺(tái)上,事件和用戶交互有很多地方的不同,基于多點(diǎn)觸控的用戶界面和基于鼠標(biāo)鍵盤有著本質(zhì)的區(qū)別,這就是為什么iOS有UIKit和UIView,但是Mac OS有AppKit和NSView
的原因。他們功能上很相似,但是在實(shí)現(xiàn)上有著顯著的區(qū)別。

繪圖,布局和動(dòng)畫,相比之下就是類似Mac筆記本和桌面系列一樣應(yīng)用于iPhone和iPad觸屏的概念。把這種功能的邏輯分開并應(yīng)用到獨(dú)立的Core Animation框架,蘋果就能夠在iOS和Mac OS之間共享代碼,使得對(duì)蘋果自己的OS開發(fā)團(tuán)隊(duì)和第三方開發(fā)者去開發(fā)兩個(gè)平臺(tái)的應(yīng)用更加便捷。

實(shí)際上,這里并不是兩個(gè)層級(jí)關(guān)系,而是四個(gè),每一個(gè)都扮演不同的角色,除了視圖層級(jí)和圖層樹之外,還存在呈現(xiàn)樹和渲染樹,將在第七章“隱式動(dòng)畫”和第十二章“性能調(diào)優(yōu)”分別討論。

圖層的能力

如果說CALayer是UIView內(nèi)部實(shí)現(xiàn)細(xì)節(jié),那我們?yōu)槭裁匆娴亓私馑兀刻O果當(dāng)然為我們提供了優(yōu)美簡(jiǎn)潔的UIView接口,那么我們是否就沒必要直接去處理Core Animation的細(xì)節(jié)了呢?

某種意義上說的確是這樣,對(duì)一些簡(jiǎn)單的需求來說,我們確實(shí)沒必要處理CALayer,因?yàn)樘O果已經(jīng)通過UIView的高級(jí)API間接地使得動(dòng)畫變得很簡(jiǎn)單。

但是這種簡(jiǎn)單會(huì)不可避免地帶來一些靈活上的缺陷。如果你略微想在底層做一些改變,或者使用一些蘋果沒有在UIView上實(shí)現(xiàn)的接口功能,這時(shí)除了介入CoreAnimation底層之外別無選擇。

我們已經(jīng)證實(shí)了圖層不能像視圖那樣處理觸摸事件,那么他能做哪些視圖不能做的呢?這里有一些UIView沒有暴露出來的CALayer的功能:

  • 陰影,圓角,帶顏色的邊框
  • 非矩形范圍
  • 陰影,圓角,帶顏色的邊框
  • 透明遮罩
  • 多級(jí)非線性動(dòng)畫

我們將會(huì)在后續(xù)章節(jié)中探索這些功能,首先我們要關(guān)注一下在應(yīng)用程序當(dāng)中CALayer是怎樣被利用起來的。

使用圖層

首先我們來創(chuàng)建一個(gè)簡(jiǎn)單的項(xiàng)目,來操縱一些layer
的屬性。打開Xcode,使用Single View Application模板創(chuàng)建一個(gè)工程。
在屏幕中央創(chuàng)建一個(gè)小視圖(大約200 X 200的尺寸),當(dāng)然你可以手工編碼,或者使用Interface Builder(隨你方便)。確保你的視圖控制器要添加一個(gè)視圖的屬性以便可以直接訪問它。我們把它稱作layerView。
運(yùn)行項(xiàng)目,應(yīng)該能在淺灰色屏幕背景中看見一個(gè)白色方塊(圖1.3),如果沒看見,可能需要調(diào)整一下背景window或者view的顏色


1.png

灰色背景上的一個(gè)白色UIView這并沒有什么令人激動(dòng)的地方,我們來添加一個(gè)色塊,在白色方塊中間添加一個(gè)小的藍(lán)色塊。
我們當(dāng)然可以簡(jiǎn)單地在已經(jīng)存在的UIView上添加一個(gè)子視圖(隨意用代碼或者IB),但這不能真正學(xué)到任何關(guān)于圖層的東西。

于是我們來創(chuàng)建一個(gè)CALayer,并且把它作為我們視圖相關(guān)圖層的子圖層。盡管UIView類的接口中暴露了圖層屬性,但是標(biāo)準(zhǔn)的Xcode項(xiàng)目模板并沒有包含Core Animation相關(guān)頭文件。所以如果我們不給項(xiàng)目添加合適的庫,是不能夠使用任何圖層相關(guān)的方法或者訪問它的屬性。所以首先需要添加QuartzCore框架到Build Phases標(biāo)簽,然后在vc的.m文件中引入庫。

之后就可以在代碼中直接引用CALayer的屬性和方法。在清單1.1中,我們用創(chuàng)建了一個(gè)CALayer,設(shè)置了它的backgroundColor屬性,然后添加到layerView背后相關(guān)圖層的子圖層(這段代碼的前提是通過IB創(chuàng)建了layerView并做好了連接),圖1.5顯示了結(jié)果。

清單1.1
- (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];
}
圖1.5.png

一個(gè)視圖只有一個(gè)相關(guān)聯(lián)的圖層(自動(dòng)創(chuàng)建),同時(shí)它也可以支持添加無數(shù)多個(gè)子圖層,從清單1.1可以看出,你可以顯示創(chuàng)建一個(gè)單獨(dú)的圖層,并且把它直接添加到視圖關(guān)聯(lián)圖層的子圖層。盡管可以這樣添加圖層,但往往我們只是見簡(jiǎn)單地處理視圖,他們關(guān)聯(lián)的圖層并不需要額外地手動(dòng)添加子圖層。

在Mac OS平臺(tái),10.8版本之前,一個(gè)顯著的性能缺陷就是由于用了視圖層級(jí)而不是單獨(dú)在一個(gè)視圖內(nèi)使用CALayer樹狀層級(jí)。但是在iOS平臺(tái),使用輕量級(jí)的UIView類并沒有顯著的性能影響(當(dāng)然在Mac OS 10.8之后,NSView的性能同樣也得到很大程度的提高)。

使用圖層關(guān)聯(lián)的視圖而不是CALayer的好處在于,你能在使用所有CALayer底層特性的同時(shí),也可以使用UIView的高級(jí)API(比如自動(dòng)排版,布局和事件處理)。

然而,當(dāng)滿足以下條件的時(shí)候,你可能更需要使用CALayer而不是UIView

  • 開發(fā)同時(shí)可以在Mac OS上運(yùn)行的跨平臺(tái)應(yīng)用
  • 使用多種CALayer的子類(見第六章,“特殊的圖層“),并且不想創(chuàng)建額外的UIView去包封裝它們所有
  • 做一些對(duì)性能特別挑剔的工作,比如對(duì)UIView一些可忽略不計(jì)的操作都會(huì)引起顯著的不同(盡管如此,你可能會(huì)直接想使用OpenGL繪圖)

但是這些例子都很少見,總的來說,處理視圖會(huì)比單獨(dú)處理圖層更加方便

總結(jié)

這一章闡述了圖層的樹狀結(jié)構(gòu),說明了如何在iOS中由UIView的層級(jí)關(guān)系形成的一種平行的CALayer層級(jí)關(guān)系,在后面的實(shí)驗(yàn)中,我們創(chuàng)建了自己的CALayer,并把它添加到圖層樹中。

在第二章,“圖層關(guān)聯(lián)的圖片”,我們將要研究一下CALayer關(guān)聯(lián)的圖片,以及Core Animation提供的操作顯示的一些特性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,957評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,081評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,485評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,720評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,263評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,025評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,204評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,461評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評(píng)論 1 289
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,945評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,205評(píng)論 2 375