本篇文章將會談論iOS開發中的關鍵議題之一layers,它為Core Animation框架的一部份,雖然讀者可能已經接觸過iOS中的Views,卻可能不知道,每個View都是透過layer做為圖形繪製的基礎。
讀者可能會想「過去開發從未碰觸到layer,它重要嗎?」,但事實上,你開發的應用程式中,layer都扮演著重要的角色,因為每個View的圖形繪製都是由layer所支持,也是因為Layers的存在,所以iOS可以輕易從應用程式裡獲取View裡面的bitmap(點陣圖)資訊,提供給裝置中的圖像處理器,請看下列圖表(擷取自Apple ),顯示Core Animation位於iOS圖形繪製的層次結構中。
為什麼需要Layers?
使用智慧手機裝置時,使用者都預期能夠處在一個順暢的操作環境中,因此,保持一致的幀率(描述視頻流更新的的頻率)是至關重要的一件事,如此才能確保提供使用者流暢的使用體驗,在iOS中,圖形處理器為每秒刷新60次的頻率,為了讓系統能維持在這個速率,一個非常基本卻強大的圖形功能layer被創造出來,並直接運行OpenGL這個圖形處理器。
OpenGL (Open Graphics Library,開放圖形庫)提供iOS圖性處理器最底層的(也是最快)訪問,但是,OpenGL就算處理極為簡單的需求,也必須透過大量的代碼去達成任務。
為了緩解這個問題,Core Graphics因運而生,它提供了較高階的功能,只需要更少的代碼就能達成任務。隨後,為了能更簡單的處理 Core Graphics的作業,再推出了Core Animation,它提供 CALayer
類別讓圖形處理器去接受部分底層的基本訪問需求。
儘管如此,蘋果仍考量許多應用程式並不需要Core Animation提供的進階圖形繪製功能,所以打造了UIKit這個應用層,它在iOS開發中,提供最高階的APIs給開發者直接使用,換句話說,UIKit的推出提供另一項選擇,讓使用者根據自己的需求選取所需的方案,不必在多寫不必要的程式碼。
但這存在一些劣勢,高階APIs在作業上也相對沒有彈性,無法滿足開發中的需求,這也告訴我們,雖然大部分的情況都不需要直接接觸到CALayer
,但是CALayer
提供較底層的APIs,讓開發者能更彈性的做出自己想要的功能,CALayer
的存在,使得iOS可以快速且輕易在應用程式的View層次結構中抓取bitmap資訊,丟給Core Graphics進行下一步作業,最終由OpenGL處理後呈現至裝置螢幕上,這篇文章將會帶讀者初步探索它。
探索CALayer
上面的篇幅已經大致講述為何會有layers存在,現在就一同探索它吧!就如同文章一開始所說,每個View都是透過layer做為圖形繪製的基礎,可以在UIView
的屬性中訪問layer
,若是你有myView
這個物件,也可以透過下列的語法,對layer
進行存取。
myView.layer
那我們訪問layer之後可以做些什麼呢?本文接下來的篇幅將帶讀者去探究相關的應用,你可能會感到很驚訝,原來它可以做到這麼多事情。
Demo Project
首先,請下載這個範例starter project,我們將會在這個app中,針對layers進行一些客製化的效果展示,最好的學習方法,則是跟上腳步一起實作。現在我們打開這個範例,你可以看到目前架構相當簡單,一個白色的view中間包含一個正方形的subview,讓我們來美化一下它,請點開ViewController.swift
準備接下來的作業。
製作圓角
你可以更改CALayer
中的屬性cornerRadius
,藉此得到圓角的圖形,請在viewDidLoad()
裡面輸入下方這行程式碼。
box.layer.cornerRadius = 5
就像我們所預期,這行程式碼將會對這個box
的layer,增加corner radius的屬性,我們將5賦值給它以後,正方形的四個角會變成圓角,就像下列這張圖。
效果看起來還不錯,若是將數值提高,則圓角的效果將會更趨顯著,反之亦然,若是沒有特別設定,corner radius的預設值為0。
增加陰影效果
陰影效果可以讓我們在app裡設計UI更有彈性,接下來,將透過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
Line #1:: 第一行是賦值給layer shadow offset,呼叫 CGSize
塞入所需數值給layer.shadowOffset
這個屬性, 傳送(5, 5)給layer.shadowOffset
表示layer的陰影顯示在box.layer
右側及下方5points的距離。
Line #2:: 第二行則是設定layer shadow的透明度,0.7代表將透明度將是原先的70%
Line #3:: 第三行為設定layer的陰影範圍為5,數值越高則陰影越模糊且分散,數值越低則會較清晰且集中。
Line #4: 第四行則是將陰影的顏色設定為深藍色,但請注意這邊的屬性特定是針對 CGColor
,而不是UIColor
,若是要進行轉換也很簡單,只要輸入myUIColor.CGColor
即可。
讓我們看一下更改屬性後的效果
邊框應用
CALayer
也讓開發者可以很輕易的對box
的邊框進行設定
box.layer.borderColor = UIColor.blueColor().CGColor box.layer.borderWidth = 3
Line #1: 第一行是將box
的邊框顏色設定為深藍色
Line #2: 第二行則是將box
的邊框寬度設定為3,賦值後box
將會出現厚度3 points的邊框。
添加上述的box
邊框設定後如下圖
展示圖片
開發者也可以將一張圖片嵌進layer,讓layer呈現這張圖片的樣子,在我們的範例中,將會透過一張樹木的圖片進行展示,圖片來源自此網站,接下來,就讓我們透過一個layer去展示這張圖片,請於viewDidLoad
貼入下列代碼。
box.layer.contents = UIImage(named: "tree.jpg")?.CGImage box.layer.contentsGravity = kCAGravityResize box.layer.masksToBounds = true
Line #1: 第一行我們先宣告一個UIImage
,並且將檔案名稱為tree.jpg
的檔案寫入,賦值給layer屬性中的contents
。
Line #2: 第二行程式碼是將這個圖層的屬性contentsGravity
設定為resize,設置後layer裡面的內容會被重新調整對齊,完美地貼合layer。
Line #3: 第三行masksToBounds
屬性若被設置為true
,會將超過邊筐外的sublayers裁切掉,若是不理解這個屬性效果為何,可以將屬性設置為false
,比較兩者不同之處。
請參考下面的對照圖
背景顏色以及透明度
我們先前談論到如何透過 CALayer
添加想要的特效,但我們也應該知道,大部分修改的 UIKit
屬性,是來自UIView
的 CALayer
元件。舉例來說,開發者可藉由下列程式碼,更改View的背景顏色與透明度。
box.layer.backgroundColor = UIColor.blueColor().CGColor box.layer.opacity = 0.5
CALayer效能表現
添加過多額外的效果會將會影響效能,但現在我們將談到兩個CALayer
的屬性,可以幫助開發者改善應用程式的效能表現。
首先,來談談異步繪製(drawsAsynchronously)
,它可以指定CPU是否讓繪製作業在背景進行,若是異步繪製被設定為true
,CPU進行繪製作業將在背景線程運作,如果你的應用程式需要頻繁進行重新繪製得作業,例如地圖或tableview頁面,那開發者應該開啟異步繪製的設定。
下一個屬性是shouldRasterize
,這個屬性在CALayer
中,將可指定layer是否 rasterized(點陣化,將對象轉換成對應像素點的過程),若是這屬性被設置為true
,layer將會被重新繪製。但請注意,當這個對象是一個動畫,它不會被重繪,且bitmap資訊會在首次繪製時就被回收。因此,這個特性應該在應用程式不會頻繁進行重繪作業時,才被設置為true
。
此外,由於CALayer 在建立完畢之後,預設都是一倍解析度,若在Retina裝置中變更shouldRasterize
屬性設定,可能看起來會糊糊的,為了防止出現這個問題,應該要告訴 CALayer
用怎樣的解析度,將rasterizationScale
設置為UIScreen.mainScreen().scale
。
還是要提醒讀者,在開發的99%時間裡面,並不會需要自己去設定上述的這些屬性,手動更改可能會影響到app的運作效能,因此,只有在已經確定視圖繪製會如何影響應用程式效能表現的時候,再考慮手動更改上述這兩項屬性的預設值。
結論
現在你已經知道什麼是CALayer
,對於繪圖底層知識有更多一點的了解後,將可以幫助你打造更酷炫的apps,希望讀者享受本篇CALayer初心者指南。
讀者可以在GitHub 下載完整Xcode項目作參考。 如果有任何問題或是回饋,歡迎踴躍在下方留言。
FB : https://www.facebook.com/yishen.chen.54
Twitter : https://twitter.com/YeEeEsS