2018-08-30

轉(zhuǎn)https://blog.csdn.net/lxl_815520/article/details/51878882

IOS進(jìn)階 - CALayer簡單介紹

2016年07月11日 13:26:30?閱讀數(shù):1550

第一部分:簡介

一塞关、什么是CALayer

* 在iOS系統(tǒng)中蒜焊,你能看得見摸得著的東西基本上都是UIView拭卿,比如一個按鈕胀溺、一個文本標(biāo)簽蜻牢、一個文本輸入框褐鸥、一個圖標(biāo)等等酬荞,這些都是UIView刻像。

? ? ?* 其實UIView之所以能顯示在屏幕上锹安,完全是因為它內(nèi)部的一個層短荐。

? ? ?* 在創(chuàng)建UIView對象時,UIView內(nèi)部會自動創(chuàng)建一個層(即CALayer對象)叹哭,通過UIView的layer屬性可以訪問這個層忍宋。當(dāng)UIView需要顯示到屏幕上時,會調(diào)用 ? ? ? ? ? ? ? ? ?drawRect:方法進(jìn)行繪圖话速,并且會將所有內(nèi)容繪制在自己的層上讶踪,繪圖完畢后,系統(tǒng)會將層拷貝到屏幕上泊交,于是就完成了UIView的顯示乳讥。

? ? ?* 換句話說,UIView本身不具備顯示的功能廓俭,是它內(nèi)部的層才有顯示功能云石。

二、UIView與CALayer的區(qū)別和聯(lián)系

*?UIView是iOS系統(tǒng)中界面元素的基礎(chǔ)研乒,所有的界面元素都繼承自它汹忠。它本身完全是由CoreAnimation來實現(xiàn)的(Mac下似乎不是這樣)。它真正的繪圖部分雹熬,是由一個叫CALayer(Core Animation Layer)的類來管理宽菜。UIView本身,更像是一個CALayer的管理器竿报,訪問它的跟繪圖和跟坐標(biāo)有關(guān)的屬性铅乡,例如frame,bounds等等烈菌,實際上內(nèi)部都是 ? ?在訪問它所包含的CALayer的相關(guān)屬性阵幸。

就是說我們在操作UIView的一些跟繪圖和坐標(biāo)有關(guān)的屬性的時候,比如, self.view.backGround =[UIColor yellowColor] ,本質(zhì)仍然是對CLayer做了操作. 由于代碼封裝我們看不到罷了.

*?UIView有個layer屬性花履,可以返回它的主CALayer實例,UIView有一個layerClass方法挚赊,返回主layer所使用的類诡壁,UIView的子類,可以通過重載這個方法荠割,來讓UIView使用不同的CALayer來顯示妹卿,例如通過

使某個UIView的子類使用GL來進(jìn)行繪制。

*?UIView的CALayer類似UIView的子View樹形結(jié)構(gòu)涨共,也可以向它的layer上添加子layer纽帖,來完成某些特殊的表示。例如下面的代碼

會在目標(biāo)View上敷上一層黑色的透明薄膜举反。

*?UIView的layer樹形在系統(tǒng)內(nèi)部懊直,被系統(tǒng)維護(hù)著三份copy(這段理解有點吃不準(zhǔn))。

第一份火鼻,邏輯樹室囊,就是代碼里可以操縱的,例如更改layer的屬性等等就在這一份魁索。

第二份融撞,動畫樹,這是一個中間層粗蔚,系統(tǒng)正在這一層上更改屬性尝偎,進(jìn)行各種渲染操作。

第三份鹏控,顯示樹致扯,這棵樹的內(nèi)容是當(dāng)前正被顯示在屏幕上的內(nèi)容。

這三棵樹的邏輯結(jié)構(gòu)都是一樣的当辐,區(qū)別只有各自的屬性抖僵。

*動畫的運作

UIView的主layer以外(我覺得是這樣),對它的subLayer缘揪,也就是子layer的屬性進(jìn)行更改耍群,系統(tǒng)將自動進(jìn)行動畫生成,動畫持續(xù)時間有 個缺省時間找筝,個人感覺大概是0.5秒蹈垢。在動畫時間里,系統(tǒng)自動判定哪些屬性更改了袖裕,自動對更改的屬性進(jìn)行動畫插值曹抬,生成中間幀然后連續(xù)顯示產(chǎn)生動畫效果。

*坐標(biāo)系系統(tǒng)(對position和anchorPoint的關(guān)系還是犯暈)

CALayer的坐標(biāo)系系統(tǒng)和UIView有點不一樣陆赋,它多了一個叫anchorPoint的屬性沐祷,它使用CGPoint結(jié)構(gòu),但是值域是0~1攒岛,也就是 按照比例來設(shè)置赖临。這個點是各種圖形變換的坐標(biāo)原點,同時會更改layer的position的位置灾锯,它的缺省值是{0.5, 0.5}兢榨,也就是在layer的中央。

某layer.anchorPoint = CGPointMake(0.f, 0.f);

如果這么設(shè)置顺饮,layer的左上角就會被挪到原來的中間的位置吵聪,

加上這樣一句就好了

某layer.position = CGPointMake(0.f, 0.f);

*layer可以設(shè)置圓角顯示,例如UIButton的效果兼雄,也可以設(shè)置陰影顯示吟逝,但是如果layer樹中的某個layer設(shè)置了圓角,樹中所有l(wèi)ayer 的陰影效果都將顯示不了了赦肋。如果既想有圓角又想要陰影块攒,好像只能做兩個重疊的UIView,一個的layer顯示圓角佃乘,一個的layer顯示陰 影.....

上面已經(jīng)說過了囱井,UIView之所以能夠顯示,完全是因為內(nèi)部的CALayer對象趣避。因此庞呕,通過操作這個CALayer對象,可以很方便地調(diào)整UIView的一些界面屬性程帕,比如:陰影住练、圓角大小、邊框?qū)挾群皖伾取?/p>

三,CALayer的頭文件

四骆捧、CALayer的簡單使用

1.CALayer是被定義在QuartzCore框架中的澎羞,因此要想使用CALayer,先導(dǎo)入QuartzCore框架(如果已經(jīng)導(dǎo)入了UIKit框架,就無需導(dǎo)入QuartzCore框架,因為UIKit本身已經(jīng)引入QuartzCore框架?)

1> 點擊項目名稱敛苇,然后點擊右邊TARGETS下面的target

2> 點擊Build Pases后妆绞,展開Link Binary....,添加 + 號

3> 在搜索框中輸入"Quartz"枫攀,選中QuartzCore.framework括饶,最后add添加

4> 添加完畢后,這個框架就會出現(xiàn)在項目文件夾中

如果你覺得位置不好看来涨,還可以將它拖到Frameworks文件夾下图焰,跟其他框架放一起

2.在項目代碼中導(dǎo)入QuartzCore框架的主頭文件

3.通過CALayer修改UIImageView的界面屬性

你也可以使用UIButton或者UILabel,這里就以UIImageView為例子

1> 先創(chuàng)建一個UIImageView蹦掐,添加到控制器的view中

2> 設(shè)置陰影

* 第1行設(shè)置陰影的顏色為灰色技羔,注意僵闯,這里使用的是UIColor的CGColor屬性,是一種CGColorRef類型的數(shù)據(jù)

* 第2行設(shè)置陰影的偏移大小藤滥,可以看出陰影往原圖的右下角偏移

* 第3行設(shè)置陰影的不透明度為0.5鳖粟,表示半透明。如果為1拙绊,代表完全不透明向图。

3> 設(shè)置圓角大小

通過layer屬性可以訪問視圖內(nèi)部的CALayer對象

* 第1行設(shè)置圓角半徑為10

* 第2行的maskToBounds=YES:可以看做是強(qiáng)制內(nèi)部的所有子層支持圓角效果,少了這個設(shè)置标沪,UIImageView是不會有圓角效果的

* 注意榄攀,如果設(shè)置了maskToBounds=YES,那將不會有陰影效果

4> 設(shè)置邊框?qū)挾群皖伾?/p>

* 第1行設(shè)置邊框?qū)挾葹?

* 第2行設(shè)置邊框顏色為紅色

5> 設(shè)置旋轉(zhuǎn)

* 利用transform屬性可以設(shè)置旋轉(zhuǎn)金句、縮放等效果

* M_PI_4表示四分之π檩赢,順時針旋轉(zhuǎn)45°

* 后面的(0, 0, 1)表示Z軸這個向量,修改這個向量可以做一些三維旋轉(zhuǎn)效果趴梢,你可以隨便改個值試一下漠畜,比如(1, 1, 1)

* 總體的意思是layer會繞著Z軸順時針旋轉(zhuǎn)45°,也就是在x坞靶、y平面進(jìn)行旋轉(zhuǎn)

第二部分:創(chuàng)建新的層

一憔狞、添加一個簡單的圖層

* 第1行創(chuàng)建了一個自動釋放的CALayer對象,你也可以使用經(jīng)典的alloc和init方法來創(chuàng)建

* 第12行將創(chuàng)建好的層添加到控制器的view的層中

二彰阴、添加一個顯示圖片的圖層

* 在第7行設(shè)置需要顯示的圖片瘾敢,注意,這里用的是UIImage的CGImage屬性尿这,是一種CGImageRef類型的數(shù)據(jù)

三簇抵、為什么CALayer中使用CGColorRef和CGImageRef這2種數(shù)據(jù)類型,而不用UIColor和UIImage射众?

* 首先要知道:CALayer是定義在QuartzCore框架中的碟摆;CGImageRef、CGColorRef兩種數(shù)據(jù)類型是定義在CoreGraphics框架中的叨橱;UIColor典蜕、UIImage是定義在UIKit框架中的

* 其次,QuartzCore框架和CoreGraphics框架是可以跨平臺使用的罗洗,在iOS和Mac OS X上都能使用愉舔,但是UIKit只能在iOS中使用

* 因此,為了保證可移植性伙菜,QuartzCore不能使用UIImage轩缤、UIColor,只能使用CGImageRef、CGColorRef

* 不過很多情況下火的,可以通過UIKit對象的特定方法壶愤,得到CoreGraphics對象,比如UIImage的CGImage方法可以返回一個CGImageRef

四馏鹤、UIView和CALayer的選擇

細(xì)心的朋友不難發(fā)現(xiàn)公你,其實前面的2個效果不僅可以通過添加層來實現(xiàn),還可以通過添加UIView來實現(xiàn)假瞬。比如,第1個紅色的層可以用一個UIView來實現(xiàn)迂尝,第2個顯示圖片的層可以用一個UIImageView來實現(xiàn)脱茉。 既然CALayer和UIView都能實現(xiàn)相同的顯示效果,那究竟該選擇誰好呢垄开?

* 其實琴许,對比CALayer,UIView多了一個事件處理的功能溉躲。也就是說榜田,CALayer不能處理用戶的觸摸事件,而UIView可以

* 所以锻梳,如果顯示出來的東西需要跟用戶進(jìn)行交互的話箭券,用UIView;如果不需要跟用戶進(jìn)行交互疑枯,用UIView或者CALayer都可以

* 當(dāng)然辩块,CALayer的性能會高一些,因為它少了事件處理的功能荆永,更加輕量級

五废亭、UIView和CALayer的其他關(guān)系

* UIView可以通過subviews屬性訪問所有的子視圖,類似地具钥,CALayer也可以通過sublayers屬性訪問所有的子層

* UIView可以通過superview屬性訪問父視圖豆村,類似地,CALayer也可以通過superlayer屬性訪問父層

* 下面再看一張UIView和CALayer的關(guān)系圖:

如果兩個UIView是父子關(guān)系骂删,那么它們內(nèi)部的CALayer也是父子關(guān)系掌动。

第三部分層的屬性

一、隱式動畫屬性

* 在前面幾講中已經(jīng)提到桃漾,每一個UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個CALayer坏匪,我們可用稱這個Layer為Root Layer(根層)。所有的非Root Layer撬统,也就是手動創(chuàng)建的CALayer對象适滓,都存在著隱式動畫。

* 與UIView不同,CALayer實際上包含了一個表現(xiàn)層和一個模型層恋追。模型層是用來在內(nèi)存中存儲必要的圖層信息的凭迹。表現(xiàn)層則是用在將圖層顯示在屏幕上,并為此做了相應(yīng)的優(yōu)化罚屋。

如果說一個動畫是隱式動畫,那就意味著用做動畫的屬性是在模型層中被修改的然后在通過表現(xiàn)層傳遞出來,并最終顯示在屏幕上。 如果動畫是顯示動畫,進(jìn)行動畫的屬性就是只存在于表現(xiàn)層的,而原始的模型層(在進(jìn)行動畫之前的)會保持不變嗅绸。這就意味著除非做其他的動作,否則在一個顯示動畫結(jié)束之后,CALayer會回到動畫開始之前的狀態(tài),因為下面的模型層并沒有被修改.

* 當(dāng)對非Root Layer的部分屬性進(jìn)行相應(yīng)的修改時脾猛,默認(rèn)會自動產(chǎn)生一些動畫效果,這些屬性稱為Animatable Properties(可動畫屬性)鱼鸠。

* 列舉幾個常見的Animatable Properties:

bounds:用于設(shè)置CALayer的寬度和高度猛拴。修改這個屬性會產(chǎn)生縮放動畫

backgroundColor:用于設(shè)置CALayer的背景色。修改這個屬性會產(chǎn)生背景色的漸變動畫

position:用于設(shè)置CALayer的位置蚀狰。修改這個屬性會產(chǎn)生平移動畫

比如:假設(shè)一開始CALayer的position為(100, 100)愉昆,然后在某個時刻修改為(200, 200),那么整個CALayer就會在短時間內(nèi)從(100, 100)這個位置平移到(200, 200)

* 我們也可以從官方文檔中查詢所有的Animatable Properties

1.點擊Window -> Organizer

2.在搜索框輸入"animatable"即可

二麻蹋、position和anchorPoint

* position和anchorPoint屬性都是CGPoint類型的

* position可以用來設(shè)置CALayer在父層中的位置跛溉,它是以父層的左上角為坐標(biāo)原點(0, 0)

* anchorPoint稱為"定位點",它決定著CALayer身上的哪個點會在position屬性所指的位置扮授。它的x芳室、y取值范圍都是0~1,默認(rèn)值為(0.5, 0.5)

1.創(chuàng)建一個CALayer刹勃,添加到控制器的view的layer中

第5行設(shè)置了myLayer的position為(100, 100)堪侯,又因為anchorPoint默認(rèn)是(0.5, 0.5),所以最后的效果是:myLayer的中點會在父層的(100, 100)位置

注意荔仁,藍(lán)色線是我自己加上去的抖格,方便大家理解,并不是默認(rèn)的顯示效果咕晋。兩條藍(lán)色線的寬度均為100雹拄。

2.若將anchorPoint改為(0, 0),myLayer的左上角會在(100, 100)位置

3.若將anchorPoint改為(1, 1)掌呜,myLayer的右下角會在(100, 100)位置

4.將anchorPoint改為(0, 1)滓玖,myLayer的左下角會在(100, 100)位置

我想,你應(yīng)該已經(jīng)明白anchorPoint的用途了吧质蕉,它決定著CALayer身上的哪個點會在position所指定的位置上势篡。它的x、y取值范圍都是0~1模暗,默認(rèn)值為(0.5, 0.5)禁悠,因此,默認(rèn)情況下兑宇,CALayer的中點會在position所指定的位置上碍侦。當(dāng)anchorPoint為其他值時,以此類推。

第四部分:自定義圖層

方法描述:創(chuàng)建一個CALayer的子類瓷产,然后覆蓋drawInContext:方法站玄,使用Quartz2D API進(jìn)行繪圖

創(chuàng)建一個CALayer的子類

2.在.m文件中覆蓋drawInContext:方法,在里面繪圖

3.在控制器中添加圖層到屏幕上

注意第7行濒旦,需要調(diào)用setNeedsDisplay這個方法株旷,才會觸發(fā)drawInContext:方法的調(diào)用,然后進(jìn)行繪圖

二尔邓、自定義層的方法2

方法描述:設(shè)置CALayer的delegate晾剖,然后讓delegate實現(xiàn)drawLayer:inContext:方法,當(dāng)CALayer需要繪圖時梯嗽,會調(diào)用delegate的drawLayer:inContext:方法進(jìn)行繪圖钞瀑。

* 這里要注意的是:不能再將某個UIView設(shè)置為CALayer的delegate,因為UIView對象已經(jīng)是它內(nèi)部根層的delegate慷荔,再次設(shè)置為其他層的delegate就會出問題。UIView和它內(nèi)部CALayer的默認(rèn)關(guān)系圖:

1.創(chuàng)建新的層缠俺,設(shè)置delegate显晶,然后添加到控制器的view的layer中

* 在第3行設(shè)置了CALayer的delegate,這里的self是指控制器

* 注意第9行壹士,需要調(diào)用setNeedsDisplay這個方法磷雇,才會通知delegate進(jìn)行繪圖

2.讓CALayer的delegate(前面設(shè)置的是控制器)實現(xiàn)drawLayer:inContext:方法

?三、其他

1.總結(jié)

無論采取哪種方法來自定義層躏救,都必須調(diào)用CALayer的setNeedsDisplay方法才能正常繪圖唯笙。

2.UIView的詳細(xì)顯示過程

* 當(dāng)UIView需要顯示時,它內(nèi)部的層會準(zhǔn)備好一個CGContextRef(圖形上下文)盒使,然后調(diào)用delegate(這里就是UIView)的drawLayer:inContext:方法崩掘,并且傳入已經(jīng)準(zhǔn)備好的CGContextRef對象。而UIView在drawLayer:inContext:方法中又會調(diào)用自己的drawRect:方法

* 平時在drawRect:中通過UIGraphicsGetCurrentContext()獲取的就是由層傳入的CGContextRef對象少办,在drawRect:中完成的所有繪圖都會填入層的CGContextRef中苞慢,然后被拷貝至屏幕

參考:

CALayer的簡單介紹

CALayer的使用

更多動畫知識:

iOS Core Animation: Advanced Techniques中文譯本

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市英妓,隨后出現(xiàn)的幾起案子挽放,更是在濱河造成了極大的恐慌,老刑警劉巖蔓纠,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辑畦,死亡現(xiàn)場離奇詭異,居然都是意外死亡腿倚,警方通過查閱死者的電腦和手機(jī)纯出,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人潦刃,你說我怎么就攤上這事侮措。” “怎么了乖杠?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵分扎,是天一觀的道長。 經(jīng)常有香客問我胧洒,道長畏吓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任卫漫,我火速辦了婚禮菲饼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘列赎。我一直安慰自己宏悦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布包吝。 她就那樣靜靜地躺著饼煞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诗越。 梳的紋絲不亂的頭發(fā)上砖瞧,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機(jī)與錄音嚷狞,去河邊找鬼块促。 笑死,一個胖子當(dāng)著我的面吹牛床未,可吹牛的內(nèi)容都是我干的竭翠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼薇搁,長吁一口氣:“原來是場噩夢啊……” “哼逃片!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起只酥,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤褥实,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后裂允,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體损离,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年绝编,在試婚紗的時候發(fā)現(xiàn)自己被綠了僻澎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片貌踏。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窟勃,靈堂內(nèi)的尸體忽然破棺而出祖乳,到底是詐尸還是另有隱情,我是刑警寧澤秉氧,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布眷昆,位于F島的核電站,受9級特大地震影響汁咏,放射性物質(zhì)發(fā)生泄漏亚斋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一攘滩、第九天 我趴在偏房一處隱蔽的房頂上張望帅刊。 院中可真熱鬧,春花似錦漂问、人聲如沸赖瞒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栏饮。三九已至,卻和暖如春勤哗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掩驱。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工芒划, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欧穴。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓民逼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涮帘。 傳聞我的和親對象是個殘疾皇子拼苍,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜调缨,今天將帶大家一窺ios動畫全貌疮鲫。在這里你可以看...
    每天刷兩次牙閱讀 8,488評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜弦叶,今天將帶大家一窺iOS動畫全貌俊犯。在這里你可以看...
    F麥子閱讀 5,110評論 5 13
  • 1 CALayer IOS SDK詳解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi閱讀 5,150評論 3 23
  • 在iOS實際開發(fā)中常用的動畫無非是以下四種:UIView動畫,核心動畫伤哺,幀動畫燕侠,自定義轉(zhuǎn)場動畫者祖。下面我們逐個介紹。...
    4b5cb36a2ee2閱讀 355評論 0 0
  • 在iOS實際開發(fā)中常用的動畫無非是以下四種:UIView動畫绢彤,核心動畫七问,幀動畫,自定義轉(zhuǎn)場動畫茫舶。 1.UIView...
    請叫我周小帥閱讀 3,094評論 1 23