《iOS Core Animation Advanced Techniques》學(xué)習(xí)筆記(三)

2. The Backing Image

A picture is worth a thousand words. An interface is worth a thousand pictures.
——Ben Shneiderman

  • CALayer 有一個(gè) id 類型的屬性 contents吩抓,但是實(shí)際上伦连,只有在你傳入一個(gè) CGImage 時(shí)才能起作用扔枫。其 id 類型的原因在于當(dāng)它在 Mac OS 上被使用時(shí),你既可以賦予這個(gè)屬性一個(gè) CGImage 或者 NSImage 痕貌,但是在 iOS 上入宦,你只能賦一個(gè) CGImage 給它,像 UIImage 這樣的也不行轿钠。

  • 實(shí)際使用 CALayer 的 contents 屬性時(shí),你需要提供的是一個(gè) CGImageRef,也就是一個(gè)指向 CGImage 結(jié)構(gòu)體的指針芽世。UIImage 有一個(gè)叫做 CGImage 的屬性妹卿,這個(gè)屬性會(huì)返回一個(gè)隱含的 CGImageRef箕宙,如果你直接把這個(gè)值賦給 CALayer 的 contents 屬性狡门,編譯時(shí)是會(huì)報(bào)錯(cuò)的,因?yàn)?CGImageRef 不是一個(gè) Cocoa 對(duì)象,它是 Core Foundation 類型的數(shù)據(jù)肤寝。所以义桂,這里我們需要用橋接(bridge cast)的方式來(lái)將其轉(zhuǎn)換成 id 類型的數(shù)據(jù):
    layer.contents = (__bridge id)image.CGImage;

  • 盡管我們可以通過(guò)設(shè)置 CALyer 的 contents 屬性來(lái)展示圖片曹抬,但是它并不是像 UIImageView 那樣專門用來(lái)展示圖片的疾宏。

  • contentsGravity 屬性:類似于 UIView 的contentMode 屬性岩馍,決定內(nèi)容的展示位置和尺寸比例蛀恩,它是一個(gè) NSString 類型的值,我們可以從系統(tǒng)的 framework 中定義的字符串常量選用自己想要的值。

  • contentScale 屬性:這個(gè)屬性定義了 layer 中圖片(contents)的像素尺寸與 view 的尺寸的比例,默認(rèn)值為 1.0庞呕,也就是說(shuō)在屏幕繪制該圖形時(shí)地啰,是按照一點(diǎn)(point)剛好就是1個(gè)像素(pixel)的分辨率來(lái)處理的盏混,如果這個(gè)值為 2.0,那就代表一點(diǎn)中顯示兩個(gè)像素的內(nèi)容(Retina 顯示屏就是這樣的分辨率)。值得注意的是鳖粟,當(dāng)你將 CALayer 的 contentGravity 屬性設(shè)為 KCAGravityResizeAspect 時(shí),contentScale 屬性是不起作用的贞瞒。UIView 也有一個(gè)類似的屬性 contentScaleFactor掰盘,但是我們很少用到。最后,在操作 CALayer 的 contents 時(shí)钢猛,一定要記得手動(dòng)設(shè)置 layer 的 contentsScale 屬性來(lái)適配屏幕分辨率:
    layer.contentScale = [UIScreen mainScreen].scale;

  • maskToBounds 屬性:類似于 UIView 的 clipsToBounds 屬性,用來(lái)裁剪超出 frame 邊界的內(nèi)容命迈。

  • contentsRect 屬性:用來(lái)在 layer 中展示圖片的一部分內(nèi)容。不像 bounds 和 frame 這些以點(diǎn)(point)為單位,contentsRect 以單元坐標(biāo)(unit coordinates)為單位勃黍,取值范圍從 0 到 1弄息,是一個(gè)相對(duì)值。contentsRect 屬性默認(rèn)值為{0, 0, 1, 1}粗恢,也就是說(shuō)圖片正好完整地顯示在 layer 的 frame 中柑晒。

A custom contentsRect (left) and the displayed contents (right).png
  • Image Sprites :對(duì) contentsRect 屬性最有意思的應(yīng)用就是能夠使用 image sprites 了。Sprites 一般用在像 Cocos2D 這樣的 2D 游戲引擎中眷射,通過(guò) OpenGL 來(lái)顯示圖片匙赞。作者 Nick Lockwood 還寫了一個(gè)關(guān)于 Sprites 的開(kāi)源庫(kù):https://github.com/nicklockwood/LayerSprites佛掖。

  • contentCenter 屬性:類似于 UIImage 的 -resizableImageWithCapInsets:方法一樣,確定一塊可伸縮的中間區(qū)域涌庭,在 layer 大小發(fā)生改變時(shí)芥被,中間區(qū)域(contentCenter)自動(dòng)伸縮,而四周不變坐榆。默認(rèn)值是{0, 0, 1, 1}拴魄。

A couple of views using the same stretchable backing image.png
  • UIView 默認(rèn)沒(méi)有實(shí)現(xiàn) -drawRect:方法,因?yàn)槿绻?UIView 只是填充了某種顏色或者它的 layer 的 contents 已經(jīng)包含了一個(gè) image 實(shí)例席镀,這樣的話 UIView 就不需要一個(gè)自定義的 backing image了匹中;當(dāng) UIView 檢測(cè)到 -drawRect:方法被實(shí)現(xiàn)了,系統(tǒng)將會(huì)為這個(gè) view 生成一個(gè) backing image愉昆,這個(gè) backing image 的像素尺寸等于 view 的尺寸乘以 contentScale 职员。如果你不需要這個(gè) backing image,你就最好不要實(shí)現(xiàn) -drawRect:方法跛溉,因?yàn)檫@樣會(huì)浪費(fèi)內(nèi)存和 CPU焊切,這也是 Apple 為什么告訴你如果不想進(jìn)行自定義繪制的話就不要留一個(gè)空的-drawRect:方法在那里的原因。

  • 當(dāng) view 第一次出現(xiàn)在屏幕上時(shí)芳室,-drawRect 方法就被自動(dòng)調(diào)用了专肪,-drawRect:方法中的自定義實(shí)現(xiàn)會(huì)被緩存起來(lái),直到 view 需要更新的時(shí)候堪侯。

  • 盡管 -drawRect:方法是 UIView 的方法嚎尤,但它實(shí)際上是由隱藏在 view 背后的 layer 來(lái)管理繪制和存儲(chǔ)圖片的。CALayer 有一個(gè)遵循 CALayerDelegate 協(xié)議的 delegate 屬性伍宦,當(dāng) CALayer 需要繪制信息時(shí)芽死,它就會(huì)詢問(wèn)它的 delegate。CALayer 在繪制時(shí)會(huì)調(diào)用其 delegate 的兩個(gè)方法:
    - (void)displayLayer:(CALayerCALayer *)layer;
    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

  • 除非你單獨(dú)用到了 CALyer 來(lái)繪制次洼,大多數(shù)情況下关贵,你根本不要實(shí)現(xiàn) CALayerDelegate 協(xié)議。因?yàn)楫?dāng) UIView 創(chuàng)建了他的附屬 layer 時(shí)卖毁,會(huì)自動(dòng)將把它自己設(shè)為那個(gè) layer 的 delegate揖曾,并且實(shí)現(xiàn)了 -displayLayer:方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亥啦,一起剝皮案震驚了整個(gè)濱河市炭剪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翔脱,老刑警劉巖奴拦,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異届吁,居然都是意外死亡粱坤,警方通過(guò)查閱死者的電腦和手機(jī)隶糕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)站玄,“玉大人枚驻,你說(shuō)我怎么就攤上這事≈昕酰” “怎么了再登?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晾剖。 經(jīng)常有香客問(wèn)我锉矢,道長(zhǎng),這世上最難降的妖魔是什么齿尽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任沽损,我火速辦了婚禮,結(jié)果婚禮上循头,老公的妹妹穿的比我還像新娘绵估。我一直安慰自己,他們只是感情好卡骂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布国裳。 她就那樣靜靜地躺著,像睡著了一般全跨。 火紅的嫁衣襯著肌膚如雪缝左。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天浓若,我揣著相機(jī)與錄音渺杉,去河邊找鬼。 笑死挪钓,一個(gè)胖子當(dāng)著我的面吹牛是越,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诵原,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼英妓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼挽放!你這毒婦竟也來(lái)了绍赛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤辑畦,失蹤者是張志新(化名)和其女友劉穎吗蚌,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體纯出,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚯妇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年敷燎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箩言。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硬贯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出陨收,到底是詐尸還是另有隱情饭豹,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布务漩,位于F島的核電站拄衰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏饵骨。R本人自食惡果不足惜翘悉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望居触。 院中可真熱鬧妖混,春花似錦、人聲如沸饼煞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)砖瞧。三九已至息堂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間块促,已是汗流浹背荣堰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竭翠,地道東北人振坚。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像斋扰,于是被迫代替她去往敵國(guó)和親渡八。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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