CALayer 新手指南

zyfcxx 8年前發布 | 5K 次閱讀 CALayer iOS開發 移動開發

這篇文章將教你一項 iOS 中的關鍵技術: 圖層(layer) 。你可能已經知道了 iOS 中的視圖,但你可能不知道每一個獨立的視圖背后都有稱為圖層的東西。圖層是 Core Animation 框架中的內容。

你也許很好奇,「我從來沒有用過一個圖層,所以它可能沒那么重要吧?」無論你知道與否,你的應用程序都會大量使用圖層。不管是什么視圖,iOS 上的視圖都會包含一個圖層。正是因為圖層的存在,iOS 可以在你的應用中輕松檢測到視圖的位圖信息,然后提供給設備的 GPU。請參照下面的圖片(來自蘋果公司),清晰地展示了 Core Animation 在 iOS 層次結構中的位置。

為什么使用圖層?

在智能手機等設備上,用戶希望他們的一切操作都很快。保持連貫的幀速率很關鍵,這樣用戶才會覺得「絲滑流暢」。在 iOS 中,幀速率是每秒 60 幀。為了保持系統能在這個速率下運作,一個直接運行在 GPU 上、非常基礎但是功能強大的圖形功能層誕生了,它就是 OpenGL

OpenGL 提供了大部分底層的(而且是最快的)訪問權限,直達 iOS 設備的圖像硬件。然而你需要做出權衡:OpenGL 太靠近底層了,即便是為了完成最簡單的任務,都需要大量的代碼。

為了能夠緩解這個問題,蘋果創建了 Core Graphics,它提供了更高級一些的方法,代碼量也隨之更少。使用 Core Graphics 的初衷是應用到一些比較底層的功能上。為了使 Core Graphics 的使用更簡單,蘋果創建了 Core Animation。它提供了 CALayer 類,并且允許一些基本的底層圖像操作。

當蘋果認為 Core Animation 中的很多高級高級功能在常規應用中并不總是需要的時候,UIKit 就誕生了,它提供了 iOS 中最頂層的圖像訪問權限。此設計方案的優點是,在你的應用中,你可以選擇你需要的圖像訪問級別并且應用它,允許你挑選并精準地選擇所需要的功能量級,使你不必編寫無用的代碼。

缺點是較高級別的圖形 API 提供的功能比較少。講這個故事是為了說明:因為 CALayer 的存在,iOS 系統可以洞悉你的應用中的視圖層次結構,快速生成層次結構的位圖信息,然后將其傳遞到 Core Graphics 中去,最終到達 OpenGL,這樣通過設備的 GPU 處理后圖像就呈現在屏幕上了。盡管在大多數情況下都不需要直接使用 CALayer ,但是較為底層的 API 為用戶提供了一些更靈活的自定義方案,我們將在本文中討論。

訪問 CALayer

關于圖層的存在緣由已經討論的夠多了。讓我們動起手來!正如我上面提到的一樣,每一個視圖都有一個圖層來支持,可以通過 UIView 的 layer 屬性訪問。假設你有一個 myView 對象,你可以像下面這樣訪問它的 layer:

myView.layer

好了,我們能夠訪問圖層了,可以用它做些什么呢?你會驚訝地發現有非常多可以做的事情。我會在本教程的剩余部分展示其中的一部分技巧和效果。

示例工程

首先,打開 模板工程 ,讓我們正式開始吧!學習的最佳途徑是動手,所以我們將向這個應用中的視圖添加自定義的效果。打開工程,你會發現它相當簡單。它是一個空白的白色視圖,中心有一個正方形的黑色子視圖。讓我們把它修飾得美觀一點。打開示例工程,跳轉到 ViewController.swift ,正式開始。

創建圓角

你可以使用 CALayer 的 cornerRadius 屬性來設定圖層邊緣的圓角。讓我們試試看。在 viewDidLoad() 中添加以下代碼:

box.layer.cornerRadius = 5

如預期的一樣,這行代碼將會給 box 的圖層增加一個半徑為 5 的圓角。看起來像這樣:

不算太壞,對吧?對于拐角大的圖形需要增加圓角的半徑,對于拐角小的圖形減小圓角的半徑。默認的,所有圖層的圓角半徑都是 0。

添加陰影效果

陰影可以幫助我們在我們的應用中創建出深度的感覺,在界面設計中非常實用。使用陰影效果,可以使視圖「浮動」在屏幕上。讓我們來看看如何使用 CALayer 創建一個陰影效果。把下面的代碼加到 ViewController 的 viewDidLoad 方法中:

box.layer.shadowOffset = CGSizeMake(5, 5)
box.layer.shadowOpacity = 0.7
box.layer.shadowRadius = 5
box.layer.shadowColor = UIColor(red: 44.0/255.0, green: 62.0/255.0, blue: 80.0/255.0, alpha: 1.0).CGColor

第一行:這一行設置圖層陰影的偏移量為(5,5)。 layer.shadowOffset 中接受一個 CGSize 類型的參數。向 layer.shadowOffset 中傳入(5,5)意味著圖層的陰影出現在 box.layer 右側 5 個點以及下方 5 個點連成的區域上。

第二行:這一行將圖層陰影的不透明度設為 0.7。這意味著陰影應該是 70% 不透明的。

第三行:這一行將圖層陰影的范圍設為 5。陰影的范圍代表了 box.layer 所創建的陰影的模糊范圍。更高的范圍值意味著陰影會更加擴散,但是可視度會降低。較低的范圍值使得陰影更加顯眼和集中。陰影范圍為0會導致根本不會有模糊。換句話說,這使得陰影與圖層保持完全相同的尺寸和形狀。

第四行:這一行設置圖層陰影的顏色為午夜藍。注意這個屬性是 CGColor 類型的,而不是一個 UIColor 。在兩種類型之間轉換非常容易。你只要寫 myUIColor.CGColor 就可以啦。

讓我們來看一下效果!

應用邊框

CALayer 還允許我們輕松地使用邊框。讓我們給 box 增加一個邊框。

box.layer.borderColor = UIColor.blueColor().CGColor
box.layer.borderWidth = 3

第一行:這一行把邊框的顏色設置為午夜藍。這會使得 box 上的任何邊框都呈現出藍色。

第二行:這一行設置邊框的寬度為 3。這意味著 box 周圍繪制的邊框將有 3 個點的厚度。

讓我們看看增加了邊框的 box 是什么樣子。

顯示圖像

你還可以把一個圖片分配給圖層,以便在圖層上展示圖片。在示例工程中有一個可愛的樹的圖片,感謝這個 網站 。讓我們用圖層來展示這張圖片。在 viewDidLoad 中加入以下代碼:

box.layer.contents = UIImage(named: "tree.jpg")?.CGImage
box.layer.contentsGravity = kCAGravityResize
box.layer.masksToBounds = true

第一行:這一行使用文件名 tree.jpg 創建了一個 UIImage 對象,然后把它傳給了圖層的 contents 屬性。

第二行:這一行設置圖層的內容重心來調整大小,這意味著圖層中的所有內容將被調整大小以便完美地適應圖層的尺寸。

第三行:我們設置 masksToBounds 為 true ,以便圖層中任何延伸到邊界外的子圖層都會在邊界處被剪裁。如果你不明白這句話的含義,你可以把這個值設置為 false ,然后查看效果。

下面是效果。

背景色和不透明度

我們已經討論過了如何向 CALayer 中添加那些在 UIKit 中無法實現的特殊效果,但我們還應該討論一下如何通過 CALayer 修改 UIKit 暴露給 UIView 的大部分屬性。例如你可以改變視圖的背景顏色和不透明度:

box.layer.backgroundColor = UIColor.blueColor().CGColor
box.layer.opacity = 0.5

CALayer 的性能

向圖層添加大量自定義效果可能會對性能產生影響。現在,我們將討論 CALayer 的兩個屬性,它們可以幫助我們大幅度提高應用程序的性能。

首先,讓我們來討論下 drawsAsynchronously 。這是屬性在 CALayer 上指定了在繪制圖層時 CPU 必須執行的那些操作是否需要在后臺線程中執行的作用。如果這個屬性被設置為 true ,圖層看起來與往常一樣,但是繪制它所需的 CPU 計算將在后臺線程中執行。如果你的應用中有一個需要大量重新繪制的視圖(例如地圖視圖或表格視圖),請將此項設為 true 。

另一個屬性是 shouldRasterize 。這是 CALayer 上的另一個屬性。它指定了是否應該對圖層進行光柵化。當這個屬性被設置為 true 的時候,圖層只被繪制一次。每當圖層被動畫化的時候,圖層不會被重繪,而是不斷復用第一次繪制時的位圖信息。如果你的應用中有一個視圖不需要頻繁重繪,則應將這個屬性設置為 true 。注意,當設置 shouldRasterize 時,圖層的外觀可能會在 Retina 屏幕的設備上有所不同。這是因為圖層存在所謂的光柵化比例,這個比例用在圖層發生光柵化的時候。要防止這種情況發生,把圖層的 rasterizationScale 設置為 UIScreen.mainScreen().scale ,這樣在圖層進行光柵化的時候會與屏幕繪制的比例保持一致。

注意,99% 的情況下你都不需要自己去設置這些屬性。手動設置它們可能導致性能低下。如果你能確定視圖或圖層的繪制正在影響應用程序的性能,你也只能自行設置這兩個屬性中的一個。

結論

現在你知道 CALayer 是什么了!了解一些比較底層的圖像知識可以幫助你在你的應用中創建一些很酷的效果。希望你喜歡這個新手指南。

 

 

 

來自:http://swift.gg/2016/11/02/calayer-introduction/

 

 本文由用戶 zyfcxx 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!