iOS動畫進階(一)圖層樹

圖層的樹狀結構

巨妖有圖層,洋蔥也有圖層,你有嗎?我們都有圖層 -- 史萊克

Core Animation其實是一個令人誤解的命名。你可能認爲它只是用來做動畫的,但實際上它是從一個叫做Layer Kit這麼一個不怎麼和動畫有關的名字演變而來,所以做動畫這只是Core Animation特性的冰山一角。

Core Animation是一個複合引擎,它的職責就是儘可能快地組合屏幕上不同的可視內容,這個內容是被分解成獨立的圖層,存儲在一個叫做圖層樹的體系之中。於是這個樹形成了UIKit以及在iOS應用程序當中你所能在屏幕上看見的一切的基礎。

在我們討論動畫之前,我們將從圖層樹開始,涉及一下Core Animation的靜態組合以及佈局特性。

圖層和視圖

如果你曾經在iOS或者Mac OS平臺上寫過應用程序,你可能會對視圖的概念比較熟悉。一個視圖就是在屏幕上顯示的一個矩形塊(比如圖片,文字或者視頻),它能夠攔截類似於鼠標點擊或者觸摸手勢等用戶輸入。視圖在層級關係中可以互相嵌套,一個視圖可以管理它的所有子視圖的位置。圖1.1顯示了一種典型的視圖層級關係

圖1.1

圖1.1 一種典型的iOS屏幕(左邊)和形成視圖的層級關係(右邊)

在iOS當中,所有的視圖都從一個叫做UIVIew的基類派生而來,UIView可以處理觸摸事件,可以支持基於Core Graphics繪圖,可以做仿射變換(例如旋轉或者縮放),或者簡單的類似於滑動或者漸變的動畫。

CALayer

CALayer類在概念上和UIView類似,同樣也是一些被層級關係樹管理的矩形塊,同樣也可以包含一些內容(像圖片,文本或者背景色),管理子圖層的位置。它們有一些方法和屬性用來做動畫和變換。和UIView最大的不同是CALayer不處理用戶的交互。

CALayer並不清楚具體的響應鏈(iOS通過視圖層級關係用來傳送觸摸事件的機制),於是它並不能夠響應事件,即使它提供了一些方法來判斷是否一個觸點在圖層的範圍之內(具體見第三章,“圖層的幾何學”)

平行的層級關係

每一個UIview都有一個CALayer實例的圖層屬性,也就是所謂的backing layer,視圖的職責就是創建並管理這個圖層,以確保當子視圖在層級關係中添加或者被移除的時候,他們關聯的圖層也同樣對應在層級關係樹當中有相同的操作(見圖1.2)。

圖1.2

圖1.2 圖層的樹狀結構(左邊)以及對應的視圖層級(右邊)

實際上這些背後關聯的圖層纔是真正用來在屏幕上顯示和做動畫,UIView僅僅是對它的一個封裝,提供了一些iOS類似於處理觸摸的具體功能,以及Core Animation底層方法的高級接口。

但是爲什麼iOS要基於UIViewCALayer提供兩個平行的層級關係呢?爲什麼不用一個簡單的層級來處理所有事情呢?原因在於要做職責分離,這樣也能避免很多重複代碼。在iOS和Mac OS兩個平臺上,事件和用戶交互有很多地方的不同,基於多點觸控的用戶界面和基於鼠標鍵盤有着本質的區別,這就是爲什麼iOS有UIKit和UIView,但是Mac OS有AppKit和NSView的原因。他們功能上很相似,但是在實現上有着顯著的區別。

繪圖,佈局和動畫,相比之下就是類似Mac筆記本和桌面系列一樣應用於iPhone和iPad觸屏的概念。把這種功能的邏輯分開並應用到獨立的Core Animation框架,蘋果就能夠在iOS和Mac OS之間共享代碼,使得對蘋果自己的OS開發團隊和第三方開發者去開發兩個平臺的應用更加便捷。

實際上,這裏並不是兩個層級關係,而是四個,每一個都扮演不同的角色,除了視圖層級和圖層樹之外,還存在呈現樹渲染樹,將在第七章“隱式動畫”和第十二章“性能調優”分別討論。

圖層的能力

如果說CALayerUIView內部實現細節,那我們爲什麼要全面地瞭解它呢?蘋果當然爲我們提供了優美簡潔的UIView接口,那麼我們是否就沒必要直接去處理Core Animation的細節了呢?

某種意義上說的確是這樣,對一些簡單的需求來說,我們確實沒必要處理CALayer,因爲蘋果已經通過UIView的高級API間接地使得動畫變得很簡單。

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

我們已經證實了圖層不能像視圖那樣處理觸摸事件,那麼他能做哪些視圖不能做的呢?這裏有一些UIView沒有暴露出來的CALayer的功能:

  • 陰影,圓角,帶顏色的邊框
  • 3D變換
  • 非矩形範圍
  • 透明遮罩
  • 多級非線性動畫

我們將會在後續章節中探索這些功能,首先我們要關注一下在應用程序當中CALayer是怎樣被利用起來的。

使用圖層

首先我們來創建一個簡單的項目,來操縱一些layer的屬性。打開Xcode,使用Single View Application模板創建一個工程。

在屏幕中央創建一個小視圖(大約200 X 200的尺寸),當然你可以手工編碼,或者使用Interface Builder(隨你方便)。確保你的視圖控制器要添加一個視圖的屬性以便可以直接訪問它。我們把它稱作layerView

運行項目,應該能在淺灰色屏幕背景中看見一個白色方塊(圖1.3),如果沒看見,可能需要調整一下背景window或者view的顏色

圖1.3

圖1.3 灰色背景上的一個白色UIView

這並沒有什麼令人激動的地方,我們來添加一個色塊,在白色方塊中間添加一個小的藍色塊。

我們當然可以簡單地在已經存在的UIView上添加一個子視圖(隨意用代碼或者IB),但這不能真正學到任何關於圖層的東西。

於是我們來創建一個CALayer,並且把它作爲我們視圖相關圖層的子圖層。儘管UIView類的接口中暴露了圖層屬性,但是標準的Xcode項目模板並沒有包含Core Animation相關頭文件。所以如果我們不給項目添加合適的庫,是不能夠使用任何圖層相關的方法或者訪問它的屬性。所以首先需要添加QuartzCore框架到Build Phases標籤(圖1.4),然後在vc的.m文件中引入庫。

圖1.4

圖1.4 把QuartzCore庫添加到項目

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

清單1.1 給視圖添加一個藍色子圖層

#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

圖1.5 白色UIView內部嵌套的藍色CALayer

一個視圖只有一個相關聯的圖層(自動創建),同時它也可以支持添加無數多個子圖層,從清單1.1可以看出,你可以顯示創建一個單獨的圖層,並且把它直接添加到視圖關聯圖層的子圖層。儘管可以這樣添加圖層,但往往我們只是見簡單地處理視圖,他們關聯的圖層並不需要額外地手動添加子圖層。

在Mac OS平臺,10.8版本之前,一個顯著的性能缺陷就是由於用了視圖層級而不是單獨在一個視圖內使用CALayer樹狀層級。但是在iOS平臺,使用輕量級的UIView類並沒有顯著的性能影響(當然在Mac OS 10.8之後,NSView的性能同樣也得到很大程度的提高)。

使用圖層關聯的視圖而不是CALayer的好處在於,你能在使用所有CALayer底層特性的同時,也可以使用UIView的高級API(比如自動排版,佈局和事件處理)。

然而,當滿足以下條件的時候,你可能更需要使用CALayer而不是UIView

  • 開發同時可以在Mac OS上運行的跨平臺應用
  • 使用多種CALayer的子類(見第六章,“特殊的圖層“),並且不想創建額外的UIView去包封裝它們所有
  • 做一些對性能特別挑剔的工作,比如對UIView一些可忽略不計的操作都會引起顯著的不同(儘管如此,你可能會直接想使用OpenGL繪圖)

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

總結

這一章闡述了圖層的樹狀結構,說明了如何在iOS中由UIView的層級關係形成的一種平行的CALayer層級關係,在後面的實驗中,我們創建了自己的CALayer,並把它添加到圖層樹中。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章