W3Cschool
恭喜您成為首批注冊(cè)用戶(hù)
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
巨妖有圖層,洋蔥也有圖層,你有嗎?我們都有圖層 -- 史萊克
Core Animation其實(shí)是一個(gè)令人誤解的命名。你可能認(rèn)為它只是用來(lái)做動(dòng)畫(huà)的,但實(shí)際上它是從一個(gè)叫做Layer Kit這么一個(gè)不怎么和動(dòng)畫(huà)有關(guān)的名字演變而來(lái),所以做動(dòng)畫(huà)這只是Core Animation特性的冰山一角。
Core Animation是一個(gè)復(fù)合引擎,它的職責(zé)就是盡可能快地組合屏幕上不同的可視內(nèi)容,這個(gè)內(nèi)容是被分解成獨(dú)立的圖層,存儲(chǔ)在一個(gè)叫做圖層樹(shù)的體系之中。于是這個(gè)樹(shù)形成了UIKit以及在iOS應(yīng)用程序當(dāng)中你所能在屏幕上看見(jiàn)的一切的基礎(chǔ)。
在我們討論動(dòng)畫(huà)之前,我們將從圖層樹(shù)開(kāi)始,涉及一下Core Animation的靜態(tài)組合以及布局特性。
如果你曾經(jīng)在iOS或者M(jìn)ac OS平臺(tái)上寫(xiě)過(guò)應(yīng)用程序,你可能會(huì)對(duì)視圖的概念比較熟悉。一個(gè)視圖就是在屏幕上顯示的一個(gè)矩形塊(比如圖片,文字或者視頻),它能夠攔截類(lèi)似于鼠標(biāo)點(diǎn)擊或者觸摸手勢(shì)等用戶(hù)輸入。視圖在層級(jí)關(guān)系中可以互相嵌套,一個(gè)視圖可以管理它的所有子視圖的位置。圖1.1顯示了一種典型的視圖層級(jí)關(guān)系
圖1.1 一種典型的iOS屏幕(左邊)和形成視圖的層級(jí)關(guān)系(右邊)
在iOS當(dāng)中,所有的視圖都從一個(gè)叫做UIVIew
的基類(lèi)派生而來(lái),UIView
可以處理觸摸事件,可以支持基于Core Graphics繪圖,可以做仿射變換(例如旋轉(zhuǎn)或者縮放),或者簡(jiǎn)單的類(lèi)似于滑動(dòng)或者漸變的動(dòng)畫(huà)。
CALayer
類(lèi)在概念上和UIView
類(lèi)似,同樣也是一些被層級(jí)關(guān)系樹(shù)管理的矩形塊,同樣也可以包含一些內(nèi)容(像圖片,文本或者背景色),管理子圖層的位置。它們有一些方法和屬性用來(lái)做動(dòng)畫(huà)和變換。和UIView
最大的不同是CALayer
不處理用戶(hù)的交互。
CALayer
并不清楚具體的響應(yīng)鏈(iOS通過(guò)視圖層級(jí)關(guān)系用來(lái)傳送觸摸事件的機(jī)制),于是它并不能夠響應(yīng)事件,即使它提供了一些方法來(lái)判斷是否一個(gè)觸點(diǎn)在圖層的范圍之內(nèi)(具體見(jiàn)第三章,“圖層的幾何學(xué)”)
每一個(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)系樹(shù)當(dāng)中有相同的操作(見(jiàn)圖1.2)。
圖1.2 圖層的樹(shù)狀結(jié)構(gòu)(左邊)以及對(duì)應(yīng)的視圖層級(jí)(右邊)
實(shí)際上這些背后關(guān)聯(lián)的圖層才是真正用來(lái)在屏幕上顯示和做動(dòng)畫(huà),UIView
僅僅是對(duì)它的一個(gè)封裝,提供了一些iOS類(lèi)似于處理觸摸的具體功能,以及Core Animation底層方法的高級(jí)接口。
但是為什么iOS要基于UIView
和CALayer
提供兩個(gè)平行的層級(jí)關(guān)系呢?為什么不用一個(gè)簡(jiǎn)單的層級(jí)來(lái)處理所有事情呢?原因在于要做職責(zé)分離,這樣也能避免很多重復(fù)代碼。在iOS和Mac OS兩個(gè)平臺(tái)上,事件和用戶(hù)交互有很多地方的不同,基于多點(diǎn)觸控的用戶(hù)界面和基于鼠標(biāo)鍵盤(pán)有著本質(zhì)的區(qū)別,這就是為什么iOS有UIKit和UIView
,但是Mac OS有AppKit和NSView
的原因。他們功能上很相似,但是在實(shí)現(xiàn)上有著顯著的區(qū)別。
繪圖,布局和動(dòng)畫(huà),相比之下就是類(lèi)似Mac筆記本和桌面系列一樣應(yīng)用于iPhone和iPad觸屏的概念。把這種功能的邏輯分開(kāi)并應(yīng)用到獨(dú)立的Core Animation框架,蘋(píng)果就能夠在iOS和Mac OS之間共享代碼,使得對(duì)蘋(píng)果自己的OS開(kāi)發(fā)團(tuán)隊(duì)和第三方開(kāi)發(fā)者去開(kāi)發(fā)兩個(gè)平臺(tái)的應(yīng)用更加便捷。
實(shí)際上,這里并不是兩個(gè)層級(jí)關(guān)系,而是四個(gè),每一個(gè)都扮演不同的角色,除了視圖層級(jí)和圖層樹(shù)之外,還存在呈現(xiàn)樹(shù)和渲染樹(shù),將在第七章“隱式動(dòng)畫(huà)”和第十二章“性能調(diào)優(yōu)”分別討論。
如果說(shuō)CALayer
是UIView
內(nèi)部實(shí)現(xiàn)細(xì)節(jié),那我們?yōu)槭裁匆娴亓私馑??蘋(píng)果當(dāng)然為我們提供了優(yōu)美簡(jiǎn)潔的UIView
接口,那么我們是否就沒(méi)必要直接去處理Core Animation的細(xì)節(jié)了呢?
某種意義上說(shuō)的確是這樣,對(duì)一些簡(jiǎn)單的需求來(lái)說(shuō),我們確實(shí)沒(méi)必要處理CALayer
,因?yàn)樘O(píng)果已經(jīng)通過(guò)UIView
的高級(jí)API間接地使得動(dòng)畫(huà)變得很簡(jiǎn)單。
但是這種簡(jiǎn)單會(huì)不可避免地帶來(lái)一些靈活上的缺陷。如果你略微想在底層做一些改變,或者使用一些蘋(píng)果沒(méi)有在UIView
上實(shí)現(xiàn)的接口功能,這時(shí)除了介入Core Animation底層之外別無(wú)選擇。
我們已經(jīng)證實(shí)了圖層不能像視圖那樣處理觸摸事件,那么他能做哪些視圖不能做的呢?這里有一些UIView
沒(méi)有暴露出來(lái)的CALayer的功能:
我們將會(huì)在后續(xù)章節(jié)中探索這些功能,首先我們要關(guān)注一下在應(yīng)用程序當(dāng)中CALayer
是怎樣被利用起來(lái)的。
首先我們來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的項(xiàng)目,來(lái)操縱一些layer
的屬性。打開(kāi)Xcode,使用Single View Application模板創(chuàng)建一個(gè)工程。
在屏幕中央創(chuàng)建一個(gè)小視圖(大約200 X 200的尺寸),當(dāng)然你可以手工編碼,或者使用Interface Builder(隨你方便)。確保你的視圖控制器要添加一個(gè)視圖的屬性以便可以直接訪問(wèn)它。我們把它稱(chēng)作layerView
。
運(yùn)行項(xiàng)目,應(yīng)該能在淺灰色屏幕背景中看見(jiàn)一個(gè)白色方塊(圖1.3),如果沒(méi)看見(jiàn),可能需要調(diào)整一下背景window或者view的顏色
圖1.3 灰色背景上的一個(gè)白色UIView
這并沒(méi)有什么令人激動(dòng)的地方,我們來(lái)添加一個(gè)色塊,在白色方塊中間添加一個(gè)小的藍(lán)色塊。
我們當(dāng)然可以簡(jiǎn)單地在已經(jīng)存在的UIView
上添加一個(gè)子視圖(隨意用代碼或者IB),但這不能真正學(xué)到任何關(guān)于圖層的東西。
于是我們來(lái)創(chuàng)建一個(gè)CALayer
,并且把它作為我們視圖相關(guān)圖層的子圖層。盡管UIView
類(lèi)的接口中暴露了圖層屬性,但是標(biāo)準(zhǔn)的Xcode項(xiàng)目模板并沒(méi)有包含Core Animation相關(guān)頭文件。所以如果我們不給項(xiàng)目添加合適的庫(kù),是不能夠使用任何圖層相關(guān)的方法或者訪問(wèn)它的屬性。所以首先需要添加QuartzCore框架到Build Phases標(biāo)簽(圖1.4),然后在vc的.m文件中引入<QuartzCore/QuartzCore.h>庫(kù)。
圖1.4 把QuartzCore庫(kù)添加到項(xiàng)目
之后就可以在代碼中直接引用CALayer
的屬性和方法。在清單1.1中,我們用創(chuàng)建了一個(gè)CALayer
,設(shè)置了它的backgroundColor
屬性,然后添加到layerView
背后相關(guān)圖層的子圖層(這段代碼的前提是通過(guò)IB創(chuàng)建了layerView
并做好了連接),圖1.5顯示了結(jié)果。
清單1.1 給視圖添加一個(gè)藍(lán)色子圖層
#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 白色UIView
內(nèi)部嵌套的藍(lán)色CALayer
一個(gè)視圖只有一個(gè)相關(guān)聯(lián)的圖層(自動(dòng)創(chuàng)建),同時(shí)它也可以支持添加無(wú)數(shù)多個(gè)子圖層,從清單1.1可以看出,你可以顯示創(chuàng)建一個(gè)單獨(dú)的圖層,并且把它直接添加到視圖關(guān)聯(lián)圖層的子圖層。盡管可以這樣添加圖層,但往往我們只是見(jiàn)簡(jiǎn)單地處理視圖,他們關(guān)聯(lián)的圖層并不需要額外地手動(dòng)添加子圖層。
在Mac OS平臺(tái),10.8版本之前,一個(gè)顯著的性能缺陷就是由于用了視圖層級(jí)而不是單獨(dú)在一個(gè)視圖內(nèi)使用CALayer
樹(shù)狀層級(jí)。但是在iOS平臺(tái),使用輕量級(jí)的UIView
類(lèi)并沒(méi)有顯著的性能影響(當(dāng)然在Mac OS 10.8之后,NSView
的性能同樣也得到很大程度的提高)。
使用圖層關(guān)聯(lián)的視圖而不是CALayer
的好處在于,你能在使用所有CALayer
底層特性的同時(shí),也可以使用UIView
的高級(jí)API(比如自動(dòng)排版,布局和事件處理)。
然而,當(dāng)滿足以下條件的時(shí)候,你可能更需要使用CALayer
而不是UIView
CALayer
的子類(lèi)(見(jiàn)第六章,“特殊的圖層“),并且不想創(chuàng)建額外的UIView
去包封裝它們所有UIView
一些可忽略不計(jì)的操作都會(huì)引起顯著的不同(盡管如此,你可能會(huì)直接想使用OpenGL繪圖)但是這些例子都很少見(jiàn),總的來(lái)說(shuō),處理視圖會(huì)比單獨(dú)處理圖層更加方便。
這一章闡述了圖層的樹(shù)狀結(jié)構(gòu),說(shuō)明了如何在iOS中由UIView
的層級(jí)關(guān)系形成的一種平行的CALayer
層級(jí)關(guān)系,在后面的實(shí)驗(yàn)中,我們創(chuàng)建了自己的CALayer
,并把它添加到圖層樹(shù)中。
在第二章,“圖層關(guān)聯(lián)的圖片”,我們將要研究一下CALayer
關(guān)聯(lián)的圖片,以及Core Animation提供的操作顯示的一些特性。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: