圖層樹
- 圖層與視圖
- 圖層的能力
- 使用圖層
- 總結
Core Animation
是一個復合引擎, 他的職責是盡可能的組合屏幕的不同的可視內容, 這個內容是被分解為獨立的圖層, 存儲在一個叫做圖層樹的體系之中, 于是這個樹形成了UIKit以及iOS應用程序當中你能在屏幕上看到的一切的基礎
在討論動畫之前, 我們將從圖層樹開始, 涉及一下core Animation
的靜態組合以及布局特性
一: 圖層與視圖
一個視圖就是在屏幕上顯示的一個矩形塊, 他能夠攔截類似鼠標點擊或者觸摸手勢等輸入行為, 視圖在層級關系中可以互相嵌套, 一個視圖可以管理他的所有子視圖的位置
在iOS中, 所有的視圖都是從一個叫做UIView的基類派生出來的, UIView可以處理觸摸事件, 可以支持基于core Graphics
繪圖, 可以做仿射變換(旋轉或者縮放). 或者簡單的類似滑動或者漸變的動畫
1.1: CALayer
CALayer
類在概念上和UIView
相似, 同樣也是一些被層級關系樹管理的矩形塊, 同樣也可以包含一些內容(圖片、文本、背景色)管理子圖層的位置, 它們有有些方法和屬性用來做動畫和變換, 和UIView最大的不同是CALayer不處理用戶的交互.
CALayer
并不清楚具體的響應鏈(iOS通過視圖層級關系來傳送觸摸事件的機制), 于是他不能夠響應事件, 即使她提供了一些方法來判斷是否一個觸電是否在圖層范圍內
1.2: 平行的層級關系
每個UIView都有一個CALayer實例的圖層屬性, 也就是所謂的backing layer
, 視圖的職責是創建并管理這個圖層, 以確保子視圖在層級關系中添加和移除的時候, 他們關聯頁同樣對應層級關系書當中的相同操作
[圖片上傳失敗...(image-e7891f-1512703987307)]
實際上這些背后關聯的圖層礙事真正用來在屏幕上下顯示和做動畫的, UIView僅僅是對他的封裝, 提供了一些iOS相關處理觸摸的具體功能, 以及Core Animation
底層方法的高級接口
但是為什么iOS要基于UIView
和CALayer
提供兩個平行的層級關系那? 為什么不用一個簡單的層級來處理所有的事情那? 原因在于職責分離
, 這樣能避免很多重復代碼
, 在iOS和MacOS兩個平臺下, 事情和用戶交互很多地方的不同, 基于多點觸控的用戶界面和基于鼠標鍵盤有著本質的區別, 這就是iOS有UIKit和UIView, 但是Mac OS有AppKit和NSView的原因, 他們功能很相似, 但是在實現上有著顯著的區別
繪圖、布局和動畫, 相比之下就是類似Mac比較本和桌面系列一樣應用于iPhone和Ipad觸屏的概念, 吧這種功能的邏輯分開并應用到獨立的Core Animation
框架中, 蘋果就能夠在iOS和Mac OS之間共享代碼, 使得對蘋果自己的OS開發團隊和第三方開發者去方法兩個平臺更加便捷
實際上, 這里并不是兩個層級關系, 而是四個,每一個都扮演不同的角色, 除了視圖層級和圖層樹之外, 還存在呈現樹和渲染樹.
1.3: 圖層的能力
如果說CALayer是UIView的內部實現細節, 那我們為什么要全面的了解他吶? 蘋果當然為我們提供了優美簡潔的UIView接口, 那么我們是否就沒有必要直接處理Core Animation
某種意義上說的的確實這樣的, 對一些簡單的需求來說, 我們沒有必要處理CALayer, 因為蘋果已經通過UIView
的高級API間接的使得動畫變得很簡單
我們已經證實圖層不能像視圖那樣帶來一些靈活上的缺陷, UIView缺少CALayer的功能
- 陰影 圓角 帶顏色的邊框
- 3D變換
- 非矩形范圍
- 透明遮罩
- 多級非線性動畫
1.4:使用圖層
首先我們來創建一個簡單的圖層, 從屏幕中央創建一個小視圖(200*200),
我們來創建一個CALayer
, 并且把它作為我們視圖相關圖層的子圖層, 我們創建一個CALayer
, 設置他的backgroundColor
屬性, 然后添加到相應的Layer上。
[圖片上傳失敗...(image-60588-1512703987307)]
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong)UIView *whiteView;
@property (nonatomic, strong)CALayer *blueLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
[self.view addSubview:self.whiteView];
[self.whiteView.layer addSublayer:self.blueLayer];
}
- (UIView *)whiteView{
if (_whiteView == nil) {
_whiteView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
_whiteView.backgroundColor = [UIColor whiteColor];
_whiteView.center = self.view.center;
}
return _whiteView;
}
- (CALayer *)blueLayer{
if (_blueLayer == nil) {
_blueLayer = [CALayer layer];
_blueLayer.frame = CGRectMake(50, 50, 100, 100);
_blueLayer.backgroundColor = [UIColor blueColor].CGColor;
}
return _blueLayer;
}
@end
使用圖層關聯的視圖而不是CALayer
的好處在于, 你可以使用CALayer
底層的特性的同時, 也可以使用UIView
的高級API(自動排版、布局和事件處理)
如果滿足一下的條件, 你可能需要使用CALayer
而不是UIView
- 開發同時可以在
Mac OS
上允許的跨平臺應用 - 使用多種
CALayer
的子類, 并且不想創建額外的UIView
去包裝他們所有 - 做一些對性能特別挑剔的工作, 比如對
UIView
一些可以忽略不計的操作都會引起顯著的不同
處理視圖比處理Layer要方便一些