《iOS Core Animation Advanced Techniques》学习笔记(三)

2. The Backing Image

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

  • CALayer 有一个 id 类型的属性 contents,但是实际上,只有在你传入一个 CGImage 时才能起作用。其 id 类型的原因在于当它在 Mac OS 上被使用时,你既可以赋予这个属性一个 CGImage 或者 NSImage ,但是在 iOS 上,你只能赋一个 CGImage 给它,像 UIImage 这样的也不行。

  • 实际使用 CALayer 的 contents 属性时,你需要提供的是一个 CGImageRef,也就是一个指向 CGImage 结构体的指针。UIImage 有一个叫做 CGImage 的属性,这个属性会返回一个隐含的 CGImageRef,如果你直接把这个值赋给 CALayer 的 contents 属性,编译时是会报错的,因为 CGImageRef 不是一个 Cocoa 对象,它是 Core Foundation 类型的数据。所以,这里我们需要用桥接(bridge cast)的方式来将其转换成 id 类型的数据:
    layer.contents = (__bridge id)image.CGImage;

  • 尽管我们可以通过设置 CALyer 的 contents 属性来展示图片,但是它并不是像 UIImageView 那样专门用来展示图片的。

  • contentsGravity 属性:类似于 UIView 的contentMode 属性,决定内容的展示位置和尺寸比例,它是一个 NSString 类型的值,我们可以从系统的 framework 中定义的字符串常量选用自己想要的值。

  • contentScale 属性:这个属性定义了 layer 中图片(contents)的像素尺寸与 view 的尺寸的比例,默认值为 1.0,也就是说在屏幕绘制该图形时,是按照一点(point)刚好就是1个像素(pixel)的分辨率来处理的,如果这个值为 2.0,那就代表一点中显示两个像素的内容(Retina 显示屏就是这样的分辨率)。值得注意的是,当你将 CALayer 的 contentGravity 属性设为 KCAGravityResizeAspect 时,contentScale 属性是不起作用的。UIView 也有一个类似的属性 contentScaleFactor,但是我们很少用到。最后,在操作 CALayer 的 contents 时,一定要记得手动设置 layer 的 contentsScale 属性来适配屏幕分辨率:
    layer.contentScale = [UIScreen mainScreen].scale;

  • maskToBounds 属性:类似于 UIView 的 clipsToBounds 属性,用来裁剪超出 frame 边界的内容。

  • contentsRect 属性:用来在 layer 中展示图片的一部分内容。不像 bounds 和 frame 这些以点(point)为单位,contentsRect 以单元坐标(unit coordinates)为单位,取值范围从 0 到 1,是一个相对值。contentsRect 属性默认值为{0, 0, 1, 1},也就是说图片正好完整地显示在 layer 的 frame 中。

A custom contentsRect (left) and the displayed contents (right).png
  • Image Sprites :对 contentsRect 属性最有意思的应用就是能够使用 image sprites 了。Sprites 一般用在像 Cocos2D 这样的 2D 游戏引擎中,通过 OpenGL 来显示图片。作者 Nick Lockwood 还写了一个关于 Sprites 的开源库:https://github.com/nicklockwood/LayerSprites

  • contentCenter 属性:类似于 UIImage 的 -resizableImageWithCapInsets:方法一样,确定一块可伸缩的中间区域,在 layer 大小发生改变时,中间区域(contentCenter)自动伸缩,而四周不变。默认值是{0, 0, 1, 1}。

A couple of views using the same stretchable backing image.png
  • UIView 默认没有实现 -drawRect:方法,因为如果 UIView 只是填充了某种颜色或者它的 layer 的 contents 已经包含了一个 image 实例,这样的话 UIView 就不需要一个自定义的 backing image了;当 UIView 检测到 -drawRect:方法被实现了,系统将会为这个 view 生成一个 backing image,这个 backing image 的像素尺寸等于 view 的尺寸乘以 contentScale 。如果你不需要这个 backing image,你就最好不要实现 -drawRect:方法,因为这样会浪费内存和 CPU,这也是 Apple 为什么告诉你如果不想进行自定义绘制的话就不要留一个空的-drawRect:方法在那里的原因。

  • 当 view 第一次出现在屏幕上时,-drawRect 方法就被自动调用了,-drawRect:方法中的自定义实现会被缓存起来,直到 view 需要更新的时候。

  • 尽管 -drawRect:方法是 UIView 的方法,但它实际上是由隐藏在 view 背后的 layer 来管理绘制和存储图片的。CALayer 有一个遵循 CALayerDelegate 协议的 delegate 属性,当 CALayer 需要绘制信息时,它就会询问它的 delegate。CALayer 在绘制时会调用其 delegate 的两个方法:
    - (void)displayLayer:(CALayerCALayer *)layer;
    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

  • 除非你单独用到了 CALyer 来绘制,大多数情况下,你根本不要实现 CALayerDelegate 协议。因为当 UIView 创建了他的附属 layer 时,会自动将把它自己设为那个 layer 的 delegate,并且实现了 -displayLayer:方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容