1、區(qū)別
1.UIView 是 UIKit 的(只能 iOS 使用),CALayer 是 QuartzCore 的(這是一個跨平臺的框架,既可以用在iOS 中又可以用在 Mac OS X中)
2. UIView 是 CALayer 的代理(delegate)。UIView 繼承 UIResponder, CALayer 繼承 NSObject, UIView 比 CALayer 多了一個事件處理的功能,也就是說,CALayer 不能處理用戶的觸摸事件,而 UIView 可以,但CALayer實現(xiàn)的是圖層內(nèi)容管理。
3.UIView 來自 CALayer,是 CALayer 的高層實現(xiàn)和封裝,UIView 的所有特性來源于 CALayer 支持
4.CABasicAnimation,CAAnimation,CAKeyframeAnimation等動畫類都需要加到CALayer上
5、在 CALayer 中很少使用 frame 屬性,因為 frame 本身不支持動畫效果,通常使用 bounds 和 position 代替。
6、CALayer 中透明度使用 opacity 表示而不是 alpha;中心點使用 position 表示而不是 center。
2、繪圖
當調(diào)用 UIView 的 drawRect: 方法繪制圖形、圖像,這種方式本質還是在圖層中繪制。只是 drawRect: 方法是由 UIKit 組件進行調(diào)用,因此里面可以使用一些 UIKit 封裝的方法進行繪圖。
直接繪制到圖層的方法由于并非 UIKit 直接調(diào)用因此只能用原生的 Core Graphics 方法繪制。
圖層繪圖有兩種方法,不管使用哪種方法繪制完必須調(diào)用圖層的 setNeedDisplay 方法(注意是圖層的方法,不是 UIView 的方法,前面我們介紹過UIView也有此方法)
2.1 通過圖層代理 drawLayer:inContext: 方法繪制
過代理方法進行圖層繪圖只要指定圖層的代理,然后在代理對象中重寫 -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 方法即可(可以通過事件參數(shù)獲得繪制的圖層和圖形上下文,在這個方法中繪圖時所有的位置都是相對于圖層而言的,圖形上下文指的也是當前圖層的圖形上下文)。
需要注意這個方法雖然是代理方法但是不用手動實現(xiàn)CALayerDelegate,因為 CALayer 定義中給 NSObject 做了分類擴展,所有的 NSObject 都包含這個方法。另外設置完代理后必須要調(diào)用圖層的 setNeedDisplay 方法,否則繪制的內(nèi)容無法顯示。
2.2 通過自定義圖層 drawInContext: 方法
在自定義圖層中繪圖時只要自己編寫一個類繼承于 CALayer 然后在 drawInContext: 中繪圖即可。同前面在代理方法繪圖一樣,要顯示圖層中繪制的內(nèi)容也要調(diào)用圖層的 setNeedDisplay 方法,否則 drawInContext 方法將不會調(diào)用。?
流程:
UIView 在顯示時其根圖層會自動創(chuàng)建一個 CGContextRef(CALayer本質使用的是位圖上下文),同時調(diào)用圖層代理(UIView 創(chuàng)建圖層會自動設置圖層代理為其自身)的 draw: inContext: 方法并將圖形上下文作為參數(shù)傳遞給這個方法。而在 UIView 的 draw:inContext: 方法中會調(diào)用其 drawRect: 方法,在 drawRect: 方法中使用 UIGraphicsGetCurrentContext() 方法得到的上下文正是前面創(chuàng)建的上下文。
3、UIXXX -> CGXXX
CALayer 是定義在 QuartzCore 框架中的,CGImageRef、CGColorRef兩種數(shù)據(jù)類型是定義在 CoreGraphics 框架中的,而 UIColor 和 UIImage 是定義在 UIKit 框架中的。
其次,QuartzCore 框架和 CoreGraphics 框架是可以跨平臺使用的,在 iOS 和 Mac OS X 上都能使用
但是 UIKit 只能在iOS中使用。
所以,為了保證可移植性,QuartzCore 不能使用 UIImage、UIColor,只能使用 CGImageRef、CGColorRef。
layer.backgroundColor = [UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
[layer setContents: (id)image.CGImage];
補充:
注意僅僅設置圓角,對于圖形而言可以正常顯示,但是對于圖層中繪制的圖片無法正確顯示,如果想要正確顯示則必須設置 masksToBounds=YES,剪切子圖層。
原因是:當繪制一張圖片到圖層上的時候會重新創(chuàng)建一個圖層添加到當前圖層,這樣一來如果設置了圓角之后雖然底圖層有圓角效果,但是子圖層還是矩形,只有設置了masksToBounds 為 YES 讓子圖層按底圖層剪切才能顯示圓角效果。
陰影效果無法和 masksToBounds 同時使用,因為 masksToBounds 的目的就是剪切外邊框, 而陰影效果剛好在外邊框。(要解決這個問題不妨換個思路:使用兩個大小一樣的圖層,下面的圖層負責繪制陰影,上面的圖層用來顯示圖片)
參考:https://blog.csdn.net/zmmzxxx/article/details/74276077