iOS --- UIView與CALayer的聯絡與區別
UIView是iOS系統中介面元素的基礎, 所有的介面元素都繼承自它, UIView本身完全是由CoreAnimation來實現. 真正的繪圖部分, 是由一個CALayer類來管理. UIView更像是一個CALayer的管理器, 所以訪問它的與繪圖和座標相關的屬性, 如frame, bounds等, 實際上都是在訪問其所包含的CALayer的相關屬性. 因此, 可以在所有UIView的子類上實現動畫效果.
UIView繼承自UIResponder, 能接收並響應事件, 負責顯示內容的管理, 而CALayer繼承自NSObject, 不能響應事件, 負責顯示內容的繪製.
UIView的layer屬性
獲取UIView的layer屬性:
CALayer *layer = self.view.layer;
UIView的layerClass方法返回layer使用的類. 可以重寫該方法, 使UIView的繼承類使用指定的CALayer來顯示, 如下程式碼可使其使用OpenGL來進行繪製.
+ (Class)layerClass {
return [CAEAGLLayer class];
}
對於UIViewController, 可做如下操作讓其UIView使用OpenGL來繪製. CALayer的層級結構與UIView的類似, addSublayer與addSubview的作用類似.
CAEAGLLayer *eaglLayer = [CAEAGLLayer layer];
eaglLayer.frame = self.view.frame;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],kEAGLDrawablePropertyRetainedBacking,kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat, nil ];
[self.view.layer addSublayer:eaglLayer];
當CALayer有了更新, 而不能立即顯示, 可使用setNeedsDisplay方法來重繪顯示.
[myLayer setNeedsDisplay];
// 更新區域性區域
[myLayer setNeedsDisplayInRect:CGRectMake(100,100,50,50)];
// CoreGraphics可以直接使用renderInContext
[myLayer renderInContext:UIGraphicsGetCurrent()];
CALayer
一個UIView可以有多個CALayer, UIView的尺寸樣式都是由內部的CALayer來提供的. 每一個CALayer顯示一種效果, 因此, 通過新增多種效果的CALayer, 以增強UIView的顯示能力. 如UIView自身不能設定圓角等效果, 而CALayer可設定邊框, 圓角, 陰影和變換變形等. 兩者都有樹狀層級結構, CALayer有subLayers, UIView有subViews.
contents屬性
CALayer *aLayer = [[CALayer alloc] init;
aLayer.contents = [[UIImage imageNamed:@"testImage"] CGImage];
aLayer.contentsGravity = kCAGravityResizeAspectFill;
這裡使用圖片給contents賦值的話, 一定要是CGImage.
可以通過設定contentsGravity設定其顯示模式, 相當於UIView的contentMode, 如kCAGravityResizeAspectFill 是鋪滿的 。kCAGravityResizeAspect 是顯示自己本身的大小 。
若果圖片超出CALayer 可以使用maskToBounds 進行裁剪 ,剪掉超出的部分 (配合圓角使用不錯)。
contentsRect
用來裁剪圖片, 預設的contentsRect是{0, 0, 1, 1}, 即整個圖都預設可見. 如果我們改成{0,0,0.5,0.5} 影象就就會被裁剪掉左上角的1/4.
CALayer效果
aLayer.backgroundColor = [[[UIColor redColor] colorWithAlphaComponent:0.2] CGColor];
// 邊框
aLayer.boardColor = [[UIColor blueColor] CGColor];
aLayer.boardWidth = 2.0;
// 圓角
aLayer.cornerRadius = 10.0;
// 陰影
aLayer.shadowColor = [[UIColor greenColor] CGColor];
aLayer.shadowOpacity = 0.5;
aLayer.shadowOffset = CGSizeMake(2, 1);
[self.view.layer addSublayer:aLayer];
圓角(cornerRadius)和陰影(shadowColor), 二者不能同時出現, 所以可以通過兩個重疊的UIView, 分別使其CALayer顯示圓角和陰影.
變換
QuartzCore的CATransform3D提供了旋轉,縮放和傾斜等變換效果.
新增3D或者仿射變換如下:
myView.layer.transform = CATransform3DMakeScale(-1.0, -1.0, 1.0);
CGAffineTransform transform = CGAffineTransformMakeRotation(45.0);
myView.layer.affineTransform = transform;
Layer Tree
CALayer內部維護著三份layer tree, 分別是presentLayer Tree(動畫樹), mode Layer Tree(模型樹), Render Tree(渲染樹), 在做iOS動畫的時候, 我們修改動畫的屬性, 在動畫的其實是Layer的presentLayer的屬性值, 而最終展示在介面上其實是提供UIView的modeLayer.
UIView與CALayer的區別
UIView繼承自UIResponder,主要特點是可以響應觸控事件。而CALayer是實際的圖層內容管理, 不會直接渲染到螢幕上。大家乾的的事情不一樣,是兩個東西,大家的存在互不影響,理所當然。
事件響應
簡單將CALayer視作只能顯示, 不能響應事件的特殊UIView; 或將UIView視作能接收和響應事件的CALayer.
UIKit使用UIResponder作為響應物件, 來響應系統傳遞過來的事件並進行處理.
UIApplication, UIViewController, UIView和所有從UIView派生出來的UIKit類(包括UIWindow)都直接或間接地繼承自UIResponder類. UIResponder中定義了處理各種事件和事件傳遞的介面.處理事件如touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:等.
而CALayer直接繼承自NSObject, 並沒有相應的處理事件的介面.
關於UIResponder的更多內容請參考以下兩篇文章:
1. Responder Chain簡析
2. 檢視和視窗架構
frame, position, bounds呼叫
一個CALayer的frame是由其anchorPoint, position, bounds, transform共同決定的, 而一個UIView的的frame只是簡單地返回CALayer的frame, 同樣UIView的center和bounds也只是簡單返回CALayer的Position和Bounds對應屬性.
機制與策略分離
UIView主要是對顯示內容的管理, 而CALayer主要是顯示內容的繪製. UIView是CALayer的CALayerDelegate, 在代理方法內部[UIView(CALayerDelegate) drawLayer:inContext]呼叫UIView的drawRect方法, 從而繪製出UIView的內容. UIView的顯示內容由內部的CALayer:display方法來實現.
程式設計問題都可以抽離出機制和策略部分。機制一旦實現,就會很少更改,但策略會經常得到優化。CALayer也可以看做是一種機制,提供圖層繪製,CALayer的標頭檔案基本上是沒怎麼變過的,而UIView可以看做是策略,變動很多。越是底層越是機制,越是機制就越是穩定。機制與策略分離,可以使得需要修改的程式碼更少,特別是底層程式碼,這樣可以提高系統的穩定性。UIView遮蔽了大部分的CALayer介面,抽取構造出更易用的frame和動畫實現,這樣上手更容易。
CALayer預設產生隱式動畫
CALayer預設修改屬性支援隱式動畫. 對於每一個 UIView 都有一個 layer,把這個 layer 且稱作RootLayer,而不是 View 的根 Layer的叫做 非 RootLayer。我們對UIView的屬性修改時時不會產生預設動畫,而對單獨 layer屬性直接修改會,這個預設動畫的時間預設值是0.25s. 即在做 iOS 動畫的時候,修改非 RootLayer的屬性(譬如位置、背景色等)會預設產生隱式動畫,而修改UIView則不會。
在給UIView的CALayer做動畫的時候, UIView作為CALayer的代理, CALayer通過actionForLayer:forKey:向UIView請求相應的動畫action.
在 Core Animation 程式設計指南的 “How to Animate Layer-Backed Views” 中,對為什麼會這樣做出了一個解釋:
UIView 預設情況下禁止了 layer 動畫,但是在 animation block 中又重新啟用了它們
是因為任何可動畫的 layer 屬性改變時,layer 都會尋找並執行合適的 ‘action’ 來實行這個改變。在 Core Animation 的專業術語中就把這樣的動畫統稱為動作 (action,或者 CAAction)。
layer 通過向它的 delegate 傳送 actionForLayer:forKey: 訊息來詢問提供一個對應屬性變化的 action。delegate 可以通過返回以下三者之一來進行響應:
它可以返回一個動作物件,這種情況下 layer 將使用這個動作。
它可以返回一個 nil, 這樣 layer 就會到其他地方繼續尋找。
它可以返回一個 NSNull 物件,告訴 layer 這裡不需要執行一個動作,搜尋也會就此停止。
當 layer 在背後支援一個 view 的時候,view 就是它的 delegate;
這部分的具體內容參考:http://objccn.io/issue-12-4/重點內容
相關推薦
UIView與CALayer有什麼區別和聯絡?
在 iOS 中,所有的 view 都是由一個底層的 layer 來驅動的。view 和它的 layer 之間有著緊密的聯絡,view 其實直接從 layer 物件中獲取了絕大多數它所需要的資料。在 iOS 中也有一些單獨的 layer,比如 AVCaptureV
Java基礎:&與&&,|與| |的聯絡與區別(詳解及示例)
&與&& 的聯絡與區別 一、&與&&的相同點 &與&& 都可作為 邏輯“與”的運算,即當運算子兩邊表示式結果都為True時,運算結果返回True;否則當某一表達式為False時,運算結果返回False 。
source 與export聯絡與使用
shell與export命令使用者登入到Linux系統後,系統將啟動一個使用者shell。在這個shell中,可以使用shell命令或宣告變數,也可以建立並執行shell指令碼程式。執行shell指令碼程式時,系統將建立一個子shell。此時,系統中將有兩個shell,一個是
iOS UIView 和 CALayer 的關係
一、概念: UIView不具備顯示功能,擁有顯示功能的是它內部的圖層即CALayer屬性 當UIView需要顯示到螢幕上時,會呼叫DrawRect:方法進行繪圖,並且將所有的內容繪製在自己的圖層上Property()CALayer *layer,繪圖完成後,
iOS --- UIView與CALayer的聯絡與區別
UIView是iOS系統中介面元素的基礎, 所有的介面元素都繼承自它, UIView本身完全是由CoreAnimation來實現. 真正的繪圖部分, 是由一個CALayer類來管理. UIView更像是一個CALayer的管理器, 所以訪問它的與繪圖和座標相關的
UIView與CALayer的區別
1、UIView是IOS系統中介面元素的基礎,所有的介面元素都繼承自它。它本身完全是由CoreAnimation來實現的(Mac下似乎不是這樣)。它真正的繪圖部分是由一個叫CALayer(Core Animation Layer)的類來管理。UIView本身,更像是一個CA
hashCode與equals的聯絡與區別
一、equals方法的作用 1、預設情況(沒有覆蓋equals方法)下equals方法都是呼叫Object類的equals方法,而Object的equals方法主要用於判斷物件的記憶體地址引用是不是同一個地址(是不是同一個物件)。 2 、要是類中覆蓋了equals方法,那麼就要根據具
Linux curl與wget 命令的區別和聯絡
當想要直接通過 Linux 命令列下載檔案,馬上就能想到兩個工具:wget 和 curl。它們有很多一樣的特徵,可以很輕易的完成一些相同的任務。 &n
反捲積、上取樣、上池化的聯絡與區別
FCN於反捲積(Deconvolution)、上取樣(UpSampling) https://blog.csdn.net/nijiayan123/article/details/79416764 反捲積(Deconvolution)、上取樣(UNSampling)與上池化(UnPooling
ARM "重定位" 與 "分散載入" 之間的聯絡與區別
目前剛剛學完了ARM的裸機部分,有一個問題一直比較困惑:就是 “重定位” 和 “分散載入” 到底是什麼關係? 首先結合S5PV210的啟動方式,iROM(BL0)中的程式執行完之後,將BL1(16K)從SD卡中複製到SRAM中執行,然後把BL2(剩餘的程式)複製到DDR中去執行。把B
java List 、Set 、Map集合聯絡與區別
List Map Set 集合 一、基礎概念 1. Collection 和 Map 介面 Java集合框架主要由 Collection和Map兩個根介面及其子介面、實現類組成。 1) Collection 介面是Set、List、和Queue介面的父介面: Coll
iOS開發知識之:pod install與pod update的區別
引言 許多使用cocoapod的人認為pod install只在第一次使用CocoaPod設定專案的時候使用,pod update是在設定完專案之後使用的,但事實並非如此。 這篇指南將會說明什麼時候應該使用pod install,什麼時候應該使用pod update。 如果你覺得這篇指南太過於
C#中的虛方法、抽象方法、抽象類、介面的聯絡與區別
虛方法的關鍵字是virtual抽象方法的關鍵字是abstract重寫都是override 虛方法也可以new虛方法和抽象方法的區別:虛方法:可以在抽象類和非抽象類中定義,可以寫在父類中,在子類中可以被重寫,在定義虛方法時必須實現虛方法 (在定義虛方法時需要寫實現方法的程式碼或者至少
Makefile和Cmake的聯絡與區別
CMake是一種跨平臺編譯工具,比make更為高階,使用起來要方便得多。CMake主要是編寫CMakeLists.txt檔案,然後用cmake命令將CMakeLists.txt檔案轉化為make所需要的makefile檔案,最後用make命令編譯原始碼生成可執行程式或共享庫(so(shared ob
Constructor&object 的聯絡與區別
constructor&object 的聯絡與區別 建構函式與物件 建構函式是類中的特殊成員函式,用於為物件分配記憶體。它可用於為資料成員提供值。建立物件時將呼叫建構函式。它與類具有相同的名稱。建構函式不返回任何值。 建構函式是生成物件的模板,一個建構函式可以生成多個物件,每個物件都有相同的結構
結構體與物件的聯絡與區別
結構體與物件的聯絡與區別 1.結構體是一種值型別,而類是引用型別。值型別用於儲存資料的值,引用型別用於儲存對實際資料的引用。 那麼結構體就是當成值來使用的,類則通過引用來對實際資料操作。 2.結構使用棧儲存(Stack Allocation),而類使用堆儲存(Heap Allocatio
C和C++的聯絡與區別
面向過程的思路:分析解決問題所需的步驟,用函式把這些步驟依次實現。 面向物件的思路:把構成問題的事務分解為各個物件,建立物件的目的,不是完成一個步驟,而是描述某個事務在解決整個問題步驟中的行為。 從上述描述可以看出,其實面向物件和麵向過程是兩種思考解決問題的方式,其差異主要在於思考的角度。
記憶體溢位與記憶體洩露的區別與聯絡,如何檢測、解決
記憶體溢位 out of memory,是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是記憶體溢位 記憶體洩露 memory leak,是指程式在申請記
RNN,LSTM和GRU和word2vec及embedding等的聯絡與區別解析。
普通的MLP和CNN都沒有事件維度,可以從RNN開始引入了事件維度,這在理解上給我們帶來了一些困難,筆者為了避免遺忘,將這種區別和特點記錄如下。 (沒時間畫圖,就看文字吧,寫的比較簡單。。。) 資料 https://zhuanlan.zhihu.com/p/36455374 這
一級域名(頂級域名),二級域名,主域名,次域名聯絡與區別及域名帶不帶www的區別
相關參考文件 域名概念: (英語:Domain Name),簡稱域名、網域,是由一串用點分隔的名字組成的Internet上某一臺計算機或計算機組的名稱,用於在資料傳輸時標識計算機的電子方位(有時也指地理位置)。 頂級域名(也叫一級域名,即倒數第一個點的右邊): ***通用頂級域*