iOS CALayer圖層漫談(二)

上一篇《iOS CALayer圖層漫談(一)》我們聊了CALayer的基本的概念和有關(guān)寄宿圖的一些屬性,這一篇呢我們來(lái)聊一下CALayer幾何學(xué)相關(guān)的事情饶火。

CALayer的布局

說(shuō)到布局我們知道UIView有三個(gè)特別重要的布局屬性:frameboundscenter近尚,CALayer同樣也有這樣三個(gè)屬性击碗,只不過(guò)center在CALayer中叫做position(為什么叫法不一樣呢丧没?這里是有原因的,后面會(huì)給大家解釋?zhuān)?/p>

平時(shí)當(dāng)我們改變UIView的frame的時(shí)候沼死,實(shí)際上是在改變視圖中l(wèi)ayer的frame着逐,也就是說(shuō)我們不能只改變UIView的frame而讓layer的frame不變,它們之間是同步的意蛀。至于這三個(gè)屬性的用法這里就不多做解釋了耸别,我想聊一下的是這三個(gè)屬性之間,以及和transform之間的一些關(guān)系县钥。

對(duì)于視圖或者圖層來(lái)說(shuō)秀姐,frame其實(shí)是一個(gè)虛擬屬性,它是根據(jù)bounds若贮、position和transform計(jì)算而來(lái)的(你可以通過(guò)下面的圖來(lái)理解)囊扳,所以當(dāng)其中任何一個(gè)值發(fā)生變化,frame都會(huì)變化兜看。反之锥咸,改變frame也會(huì)影響到他們當(dāng)中的值。

通常情況下细移,frame的寬高和bounds的寬高是相同的搏予,但是當(dāng)改變了transform的時(shí)候,frame的寬高和bounds的寬高可能就不再相同了弧轧。通過(guò)下圖大家可以理解一下這些屬性之間的關(guān)系:

CALayer的“圖釘說(shuō)” -- 錨點(diǎn)

在聊錨點(diǎn)之前雪侥,我們有必要重新認(rèn)識(shí)一下center屬性和position屬性。我們知道精绎,這兩個(gè)屬性都是設(shè)置當(dāng)前視圖(或圖層)的中心點(diǎn)在父視圖(或父圖層)坐標(biāo)系統(tǒng)中位置速缨,從而確定當(dāng)前視圖(或圖層)在父視圖(或父圖層)位置。作為視圖這個(gè)點(diǎn)是當(dāng)前視圖的中心點(diǎn)代乃,但是對(duì)于圖層來(lái)說(shuō)可能就不是中心點(diǎn)了旬牲。

在CALayer中有一個(gè)屬性叫做anchorPoint仿粹,也就是我們接下來(lái)要說(shuō)的錨點(diǎn)。但是在UIView中原茅,這個(gè)屬性并沒(méi)有被接口暴露出來(lái)吭历,這也是為什么UIView的position屬性被叫做center的原因,因?yàn)?code>center包含了位置+中心兩層含義擂橘,center其實(shí)是由positionanchorPoint兩個(gè)屬性疊加得到的晌区,此時(shí)anchorPoint對(duì)應(yīng)的值是默認(rèn)的中心點(diǎn)位置。

那么positionanchorPoint到底代表什么呢通贞?下面我們通過(guò)一個(gè)物理模型“圖釘說(shuō)”來(lái)幫助大家理解一下(請(qǐng)牢記這個(gè)模型):

我們可以把當(dāng)前圖層比作一張紙朗若,父圖層比作一面墻。我們通過(guò)positionanchorPoint屬性將當(dāng)前圖層添加到父圖層上昌罩,其實(shí)就相當(dāng)于拿一枚圖釘將這張紙固定到這面墻上捡偏。那么positionanchorPoint分別代表這個(gè)物理模型中的什么呢?這里圖釘穿過(guò)紙張的位置就是anchorPoint錨點(diǎn)的位置峡迷,圖釘扎在墻上的位置就是position的位置银伟。也就是說(shuō)anchorPoint錨點(diǎn)的位置是相對(duì)于當(dāng)前圖層的,而position是相對(duì)于父圖層的绘搞。

【 這里要說(shuō)明一點(diǎn)的是:anchorPoint使用的坐標(biāo)系統(tǒng)跟我們上篇文章提到的contentsRect是一樣的彤避,使用的是相對(duì)坐標(biāo)系統(tǒng),也就是說(shuō)左上角的坐標(biāo)是{0,0}右下角的坐標(biāo)是{1,1}夯辖。并且我們也可以通過(guò)設(shè)置小于0或大于1的值琉预,把錨點(diǎn)放置在圖層范圍之外≥锕樱】

看完上面這個(gè)物理模型之后圆米,我們?cè)賮?lái)思考這樣一個(gè)問(wèn)題:如果在position不變的情況下改變anchorPoint,此時(shí)會(huì)發(fā)生什么變化啄栓?繼續(xù)利用上面的模型娄帖,相當(dāng)于我們將圖釘摘下,從紙的另一個(gè)位置穿過(guò)昙楚,然后重新扎回上次的位置近速。此時(shí)圖釘在墻上的位置不變,但是紙張相對(duì)墻的位置卻發(fā)生了變化堪旧,其實(shí)也就是frame發(fā)生了變化削葱。我們可以通過(guò)下圖進(jìn)行進(jìn)一步的理解:

關(guān)于anchorPointposition就先聊這么多,如果想找一個(gè)應(yīng)用場(chǎng)景通過(guò)代碼來(lái)深入理解一下anchorPointposition的話(huà)淳梦,可以去看我的另一篇文章《iOS制作一個(gè)模擬時(shí)鐘》析砸,文中模擬時(shí)鐘的制作就用到了錨點(diǎn)的知識(shí)。這里還要給大家補(bǔ)充另外一個(gè)知識(shí)點(diǎn):當(dāng)一個(gè)圖層通過(guò)transform進(jìn)行旋轉(zhuǎn)的時(shí)候爆袍,圖層所圍繞的中心就是錨點(diǎn)首繁,這跟我們上面提到的物理模型也是相吻合的作郭。

CALayer的“空間”轉(zhuǎn)換

我們知道不管是UIView還是CALayer,它們的位置定義都是相對(duì)于它們的父視圖(或圖層)的蛮瞄,我們拿到也是它們相對(duì)于父視圖(或圖層)坐標(biāo)系統(tǒng)的位置信息所坯。但是有時(shí)候我們想知道的并不是它們相對(duì)于父視圖(或圖層)坐標(biāo)系統(tǒng)的位置信息谆扎,而是它們的絕對(duì)位置或者相對(duì)于其他視圖(或圖層)的位置怎么辦呢挂捅?

CALayer給我們提供了一些很友好的方法:

- (CGPoint)convertPoint:(CGPoint)p fromLayer:(nullable CALayer *)l;
- (CGPoint)convertPoint:(CGPoint)p toLayer:(nullable CALayer *)l;
- (CGRect)convertRect:(CGRect)r fromLayer:(nullable CALayer *)l;
- (CGRect)convertRect:(CGRect)r toLayer:(nullable CALayer *)l;

我們知道在iOS上坐標(biāo)系的原點(diǎn)通常位于左上角,但是在MacOS上通常是位于左下角堂湖,跟我們通诚邢龋現(xiàn)實(shí)中使用的x/y軸坐標(biāo)系是一樣的。在CALayer中无蜂,它提供了一個(gè)屬性叫做geometryFlipped伺糠,我們可以通過(guò)這個(gè)屬性對(duì)坐標(biāo)系進(jìn)行翻轉(zhuǎn),當(dāng)設(shè)置成YES后斥季,iOS中训桶,坐標(biāo)原點(diǎn)變?yōu)樵谧笙陆牵籑acOS中酣倾,坐標(biāo)原點(diǎn)變?yōu)樵谧笊辖恰?/p>

和UIView所在的二維坐標(biāo)系統(tǒng)不同舵揭,CALayer是存在于一個(gè)三維空間中的,除了上面說(shuō)過(guò)的positionanchorPoint屬性外躁锡,CALayer還有另外兩個(gè)屬性zPositionanchorPointZ午绳,這兩個(gè)浮點(diǎn)型屬性是用來(lái)描述圖層在z軸方向上的位置,而z軸的方向是垂直于屏幕平面指向人眼方向的映之。當(dāng)我們?cè)O(shè)置各圖層的這兩個(gè)屬性的時(shí)候拦焚,由于各圖層在z軸方向上分布的位置不同,就會(huì)產(chǎn)生前后遮擋的位置關(guān)系杠输,從而改變圖層樹(shù)的層級(jí)關(guān)系赎败。雖然這個(gè)兩個(gè)屬性我們平時(shí)很少用到,但是在涉及CATransform3D三維空間移動(dòng)和旋轉(zhuǎn)圖層的時(shí)候就會(huì)經(jīng)常出現(xiàn)蠢甲。

CALayer作為事件響應(yīng)的“輔助英雄”

在上一篇文章開(kāi)始我們就提到螟够,CALayer并不能獨(dú)立的完成事件響應(yīng),它也不能直接處理觸摸事件或者手勢(shì)峡钓。但是作為UIView的“輔助”妓笙,它還是要做一些“輔助英雄”該干的事兒的。

CALayer提供了兩個(gè)方法:-containsPoint:-hitTest:能岩。

-containsPoint:方法接收一個(gè)在本圖層坐標(biāo)系下的CGPoint對(duì)象寞宫,如果在圖層范圍內(nèi),就返回YES拉鹃,這樣我們就可以通過(guò)遍歷視圖樹(shù)(注意這里指的是視圖樹(shù)而不是圖層樹(shù))的方式找出應(yīng)該接收觸摸事件的圖層以及它對(duì)應(yīng)的UIView辈赋。但是這樣做實(shí)在是太麻煩了鲫忍,我們不但要手動(dòng)的遍歷視圖樹(shù),還要將觸摸點(diǎn)逐個(gè)轉(zhuǎn)換成每個(gè)圖層坐標(biāo)系下的點(diǎn)钥屈。為此CALayer給我們提供了另外一個(gè)方法-hitTest:悟民。

-hitTest:方法接收的同樣是一個(gè)CGPoint對(duì)象,但是返回值不是BOOL類(lèi)型了篷就,而是圖層本身射亏,或者包含這個(gè)觸摸坐標(biāo)點(diǎn)的葉子節(jié)點(diǎn)圖層。也就是說(shuō)-hitTest:方法會(huì)自動(dòng)幫我們遍歷它跟它的子圖層竭业,并返回包含這個(gè)坐標(biāo)點(diǎn)的圖層智润,如果都不包含則返回nil

這里要說(shuō)一下為什么上文中說(shuō)遍歷的是視圖樹(shù)而不是圖層樹(shù)未辆,因?yàn)樵谥傲?code>zPosition屬性的時(shí)候說(shuō)過(guò)窟绷,改變zPosition屬性值得時(shí)候會(huì)改變圖層樹(shù)的層級(jí)關(guān)系,但是此時(shí)layer對(duì)應(yīng)的視圖樹(shù)的層級(jí)關(guān)系是不發(fā)生變化的咐柜,所以說(shuō)對(duì)于觸摸手勢(shì)的傳遞順序還是按照視圖樹(shù)的層次順序來(lái)兼蜈,所以這樣就會(huì)導(dǎo)致更改了zPosition值位置靠前的圖層視圖不響應(yīng)觸摸手勢(shì)的問(wèn)題。

CALayer的自適應(yīng)

在iOS開(kāi)發(fā)中我們經(jīng)常使用自動(dòng)布局相關(guān)的一些API拙友,但是對(duì)于CALayer來(lái)說(shuō)自動(dòng)布局還是相對(duì)較弱的为狸,當(dāng)然這只是在iOS中是這樣,在MacOS中我們可以通過(guò)CALayerManager協(xié)議和CAConstraintLayoutManager類(lèi)來(lái)實(shí)現(xiàn)自動(dòng)排版的機(jī)制献宫,而在iOS中如果想隨意控制CALayer的布局钥平,就需要手動(dòng)操作了。最簡(jiǎn)便的方法就是使用CALayerDelegate中的代理方法:

- (void)layoutSublayersOfLayer:(CALayer *)layer;

當(dāng)圖層的bounds發(fā)生變化姊途,或者圖層的-setNeedsLayout方法被調(diào)用涉瘾,這個(gè)代理方法就會(huì)被執(zhí)行,然后我們就可以在代理方法中重新手動(dòng)的擺放調(diào)整子圖層的位置大小了捷兰,但是不能像UIView的autoresizingMaskconstraints屬性做到自適應(yīng)屏幕旋轉(zhuǎn)立叛。所以在iOS中涉及到自適應(yīng)布局的時(shí)候還是推薦使用UIView暴露出來(lái)的UIViewAutoresizingMaskNSLayoutConstraint的API接口。


下一篇《iOS CALayer圖層漫談(三)》我們將聊一聊CALayer視覺(jué)效果相關(guān)的一些事情贡茅。

版權(quán)聲明:出自MajorLMJ技術(shù)博客的原創(chuàng)作品 秘蛇,轉(zhuǎn)載時(shí)必須注明出處及相應(yīng)鏈接!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末顶考,一起剝皮案震驚了整個(gè)濱河市赁还,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驹沿,老刑警劉巖艘策,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異渊季,居然都是意外死亡朋蔫,警方通過(guò)查閱死者的電腦和手機(jī)罚渐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)驯妄,“玉大人荷并,你說(shuō)我怎么就攤上這事∏嗳樱” “怎么了源织?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)赎懦。 經(jīng)常有香客問(wèn)我雀鹃,道長(zhǎng)幻工,這世上最難降的妖魔是什么励两? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮囊颅,結(jié)果婚禮上当悔,老公的妹妹穿的比我還像新娘。我一直安慰自己踢代,他們只是感情好盲憎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著胳挎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上椒拗,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天茵典,我揣著相機(jī)與錄音,去河邊找鬼医窿。 笑死磅甩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的姥卢。 我是一名探鬼主播卷要,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼独榴!你這毒婦竟也來(lái)了僧叉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤棺榔,失蹤者是張志新(化名)和其女友劉穎瓶堕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體掷豺,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捞烟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年薄声,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片题画。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡默辨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出苍息,到底是詐尸還是另有隱情缩幸,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布竞思,位于F島的核電站表谊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盖喷。R本人自食惡果不足惜爆办,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望课梳。 院中可真熱鬧距辆,春花似錦、人聲如沸暮刃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)椭懊。三九已至诸蚕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氧猬,已是汗流浹背背犯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狂窑,地道東北人媳板。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像泉哈,于是被迫代替她去往敵國(guó)和親蛉幸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353