iOS中UIView與CALayer的關(guān)系


在 iOS 中,所有的 view 都是由一個(gè)底層的 layer 來驅(qū)動(dòng)的。view 和它的 layer 之間有著緊密的聯(lián)系,UIView繼承自UIResponder, 能接收并響應(yīng)事件, 負(fù)責(zé)顯示內(nèi)容的管理, 而CALayer繼承自NSObject, 不能響應(yīng)事件, 負(fù)責(zé)顯示內(nèi)容的繪制,view 其實(shí)直接從 layer 對(duì)象中獲取了絕大多數(shù)它所需要的數(shù)據(jù)。在 iOS 中也有一些單獨(dú)的 layer,比如 AVCaptureVideoPreviewLayer 和 CAShapeLayer,它們不需要附加到 view 上就可以在屏幕上顯示內(nèi)容。兩種情況下其實(shí)都是 layer 在起決定作用。當(dāng)然了,附加到 view 上的 layer 和單獨(dú)的 layer 在行為上還是稍有不同的。

基本上你改變一個(gè)單獨(dú)的 layer 的任何屬性的時(shí)候,都會(huì)觸發(fā)一個(gè)從舊的值過渡到新值的簡(jiǎn)單動(dòng)畫(這就是所謂的可動(dòng)畫 animatable)。然而,如果你改變的是 view 中 layer 的同一個(gè)屬性,它只會(huì)從這一幀直接跳變到下一幀。盡管兩種情況中都有 layer,但是當(dāng) layer 附加在 view 上時(shí),它的默認(rèn)的隱式動(dòng)畫的 layer 行為就不起作用了。

animatable;幾乎所有的層的屬性都是隱性可動(dòng)畫的。你可以在文檔中看到它們的簡(jiǎn)介是以 'animatable' 結(jié)尾的。這不僅包括了比如位置,尺寸,顏色或者透明度這樣的絕大多數(shù)的數(shù)值屬性,甚至也囊括了像 isHidden 和 doubleSided 這樣的布爾值。 像 paths 這樣的屬性也是 animatable 的,但是它不支持隱式動(dòng)畫。

在 Core Animation 編程指南的 “How to Animate Layer-Backed Views” 中,對(duì)為什么會(huì)這樣做出了一個(gè)解釋:

UIView 默認(rèn)情況下禁止了 layer 動(dòng)畫,但是在 animation block 中又重新啟用了它們

這正是我們所看到的行為;當(dāng)一個(gè)屬性在動(dòng)畫 block 之外被改變時(shí),沒有動(dòng)畫,但是當(dāng)屬性在動(dòng)畫 block 內(nèi)被改變時(shí),就帶上了動(dòng)畫。對(duì)于這是如何發(fā)生的這一問題的答案十分簡(jiǎn)單和優(yōu)雅,它優(yōu)美地闡明和揭示了 view 和 layer 之間是如何協(xié)同工作和被精心設(shè)計(jì)的。

無論何時(shí)一個(gè)可動(dòng)畫的 layer 屬性改變時(shí),layer 都會(huì)尋找并運(yùn)行合適的 'action' 來實(shí)行這個(gè)改變。在 Core Animation 的專業(yè)術(shù)語中就把這樣的動(dòng)畫統(tǒng)稱為動(dòng)作 (action,或者 CAAction)。

CAAction:技術(shù)上來說,這是一個(gè)接口,并可以用來做各種事情。但是實(shí)際中,某種程度上你可以只把它理解為用來處理動(dòng)畫。

layer 將像文檔中所寫的的那樣去尋找動(dòng)作,整個(gè)過程分為五個(gè)步驟。第一步中的在 view 和 layer 中交互的部分是最有意思的:
layer 通過向它的 delegate 發(fā)送 actionForLayer:forKey: 消息來詢問提供一個(gè)對(duì)應(yīng)屬性變化的 action。delegate 可以通過返回以下三者之一來進(jìn)行響應(yīng):

1.它可以返回一個(gè)動(dòng)作對(duì)象,這種情況下 layer 將使用這個(gè)動(dòng)作。
2.它可以返回一個(gè) nil, 這樣 layer 就會(huì)到其他地方繼續(xù)尋找。
3.它可以返回一個(gè) NSNull 對(duì)象,告訴 layer 這里不需要執(zhí)行一個(gè)動(dòng)作,搜索也會(huì)就此停止。

而讓這一切變得有趣的是,當(dāng) layer 在背后支持一個(gè) view 的時(shí)候,view 就是它的 delegate;

在 iOS 中,如果 layer 與一個(gè) UIView 對(duì)象關(guān)聯(lián)時(shí),這個(gè)屬性必須被設(shè)置為持有這個(gè) layer 的那個(gè) view。

理解這些之后,前一分鐘解釋起來還復(fù)雜無比的現(xiàn)象瞬間就易如反掌了:屬性改變時(shí) layer 會(huì)向 view 請(qǐng)求一個(gè)動(dòng)作,而一般情況下 view 將返回一個(gè) NSNull,只有當(dāng)屬性改變發(fā)生在動(dòng)畫 block 中時(shí),view 才會(huì)返回實(shí)際的動(dòng)作。你可以非常容易地驗(yàn)證到底是不是這樣。只要對(duì)一個(gè)一般來說可以動(dòng)畫的 layer 屬性向 view 詢問動(dòng)作就可以了,比如對(duì)于 'position':

  NSLog(@"outside animation block: %@",
[myView actionForLayer:myView.layer forKey:@"position"]);

 [UIView animateWithDuration:0.3 animations:^{
      NSLog(@"inside animation block: %@",
      [myView actionForLayer:myView.layer forKey:@"position"]);
}];

運(yùn)行上面的代碼,可以看到在 block 外 view 返回的是 NSNull 對(duì)象,而在 block 中時(shí)返回的是一個(gè) CABasicAnimation。很優(yōu)雅,對(duì)吧?值得注意的是打印出的 NSNull 是帶著一對(duì)尖括號(hào)的 ("<null>"),這和其他對(duì)象一樣,而打印 nil 的時(shí)候我們得到的是普通括號(hào)((null)):

outside animation block: <null>
inside animation block: <CABasicAnimation: 0x8c2ff10>

對(duì)于 view 中的 layer 來說,對(duì)動(dòng)作的搜索只會(huì)到第一步為止(至少我沒有見過 view 返回一個(gè) nil 然后導(dǎo)致繼續(xù)搜索動(dòng)作的情況)。對(duì)于單獨(dú)的 layer 來說,剩余的四個(gè)步驟可以在 CALayer 的 actionForKey: 文檔中找到。

節(jié)選自Objc

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,270評(píng)論 5 13
  • 1 CALayer IOS SDK詳解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi閱讀 5,336評(píng)論 3 23
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,657評(píng)論 1 32
  • 前言 本文只要描述了iOS中的Core Animation(核心動(dòng)畫:隱式動(dòng)畫、顯示動(dòng)畫)、貝塞爾曲線、UIVie...
    GitHubPorter閱讀 3,741評(píng)論 7 11
  • 一 關(guān)于CoreAnimation CoreAnimation是蘋果提供的一套基于繪圖的動(dòng)畫框架,下圖是官方文檔中...
    路飛_Luck閱讀 5,265評(píng)論 3 23

友情鏈接更多精彩內(nèi)容