学习笔记

contents属性

CALayer有叁特性子叫做contents,那一个天性的类型被定义为AnyObject?,意味着它能够是可空的任性档次对象。在那种状态下,能够给contents属性赋任何值,你的App依旧能够编译通过。可是在实践中,假诺给contents赋的不是CGImage,那么图层将是空白的。

contents属性类型之所以被定义为AnyObject?,是因为在Mac
OS系统上,那性子情对CGImage和NSImage类型的值都起效果。假诺在iOS平台军长UIImage的值赋给它,只可以得到二个空手的图层。

轶事上二个德姆oCode,大家这一次间接把layerView的宿主图层的contents属性设置成图片

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var layerView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()

    let image = UIImage(named: "snowman")

    self.layerView.layer.contents = image?.CGImage
  }
}

UIView的宿主图层中展现一张图纸

>图片胜过万语千言,界面抵得上千图形——Ben Shneiderman

contentGravity属性

在运用UIImageView的时候境遇过图片被拉伸的景况,化解方案正是把contentMode属性设置成有个别合适的值,例如:

imageView.contentMode = .ScaleAspectFit

CALayer与contentMode对应的性情叫做contentsGravity,不过它是3个String类型,而不是二个枚举类型。contentsGravity可选的常用值有以下那些:

  • kCAGravityCenter
  • kCAGravityTop
  • kCAGravityBottom
  • kCAGravityLeft
  • kCAGravityRight
  • kCAGravityTopLeft
  • kCAGravityTopRight
  • kCAGravityBottomLeft
  • kCAGravityBottomRight
  • kCAGravityResize
  • kCAGravityResizeAspect
  • kCAGravityResizeAspectFill

和contentMode壹样,contentsGravity的指标是为着控制内容在图层的边际中哪些对齐,假诺使用kCAGravityResizeAspect,它的功能等同UIViewContentModeScaleAspectFit,同时它还可以在图层中等比例拉伸以适应图层的分界。

self.layerView.layer.contentsGravity = kCAGravityResizeAspect

我们在首先章『图层树』中介绍了CALayer类并创办了2个简练的有卡其灰背景的图层。背景颜色还好啦,可是即便它仅仅是显示了3个枯燥的颜色未免也太无聊了。事实上CALayer类能够蕴涵一张你欢畅的图片,这1章节大家以后探索CALayer的寄宿图(即图层中包蕴的图)。

contentScale属性

contentScale属性定义了寄宿图的像素尺寸和视图大小的比重,暗中认可意况下它是三个值为1.0的浮点数。

contentScale属性其实属于支持高分辨率荧屏机制的一片段。它用来判定在绘制图层的时候理应为寄宿图创设的空中尺寸和急需呈现的图形的拉伸度。

万1contentScale值为一.0,将会以每1个点一个像素绘制图片,纵然设置为2.0,则会以每一个点3个像素绘制图片,正是熟识的Retina显示屏。

当用代码的办法来处理寄宿图时候,一定要牢记要手动的装置图层的contentScale属性,不然图片在Retina设备上就体现不科学。

self.layerView.layer.contentsScale = UIScreen.mainScreen().scale

##contents属性

masksToBounds属性

UIView有三个叫clipToBounds的属性,能够用来支配是还是不是出示超过边界的剧情,CALayer对应的性质叫做masksToBounds,设置值为true,内容就不会超过边界了。

self.layerView.layer.masksToBounds = true

图:使用masksToBounds来建造图层内容

CALayer有五特特性叫做`contents`,这一个天性的档次被定义为id,意味着它能够是其他项目标对象。在那种意况下,你能够给`contents`属性赋任何值,你的app依然能够编译通过。可是,在实践中,假若您给`contents`赋的不是CGImage,那么你拿走的图层将是空白的。

contentsRect属性

CALayer的contentsRect属性允许在图层边框里呈现寄宿图的3个子域。

和bounds、frame差异,contentsRect不是遵照点来计量的,它利用的是单位坐标,单位坐标钦定在0到一里边,是多个相对值(像素和点就是绝对值)。

iOS使用了以下的坐标种类

  • 点:在iOS和Mac
    OS中最普遍的坐标种类。点就好像虚拟的像素,也被称作逻辑像素。在正儿8经配备上,三个点就是二个像素,然而在Retina设备上,二个点等于二1个像素或3贰个像素。iOS用点作为显示器的坐标测算种类就是为着在Retina设备和平时设备上能有一致的视觉效果。
  • 像素:物理像素坐标并不会用来显示屏布局,可是依旧与图片有相对关系。UIImage是叁个显示器分辨率化解方案,所以钦赐点来衡量尺寸。不过有个别平底的图片表示,如CGImage就会使用像素,所以我们要明白在Retina设备和常见设备上,它们表现出来了区别的分寸。
  • 单位:对于与图片大小或是图层边界相关的来得,单位坐标是2个方便人民群众的气量情势,当大小改变的时候,也不供给重新调整。单位坐标在OpenGL这种纹理坐标类别有效的很多,Core
    Animation中也使用了单位坐标。

默许的contentsRect值是{0,0,一,壹},意味着任何寄宿图暗中认可都以可知的。

实际给contentsRect设置3个负数的原点或是大于{一,1}的尺码也得以。这种情景下,最外侧的像素会被拉伸以填充剩下的区域。

上边进入1些代码,能够只突显snowman的右上角二5%的剧情,而layer的轻重保持不变,所以展示的始末会被拉伸。

// 选择右上角四分之一为内容
self.layerView.layer.contentsRect = CGRectMake(0.5, 0, 0.5, 0.5)
//拉伸
self.layerView.layer.contentsGravity = kCAGravityResize

展示右上角二五%剧情,且拉伸

`contents`那些意外的展现是由Mac
OS的历史由来导致的。它之所以被定义为id类型,是因为在Mac
OS系统上,那几个天性对CGImage和NSImage类型的值都起效果。如若您准备在iOS平台中将UIImage的值赋给它,只好取得2个空白的图层。1些初识Core
Animation的iOS开发者大概会对这些感觉纳闷。

contentsCenter属性

从contentsCenter属性名字看,初学者很有一点都不小可能以为它和图纸的职位有关,但是这些名字误导了您。
contentsCenter其实是二个CGRect,它定义了贰个固定的边框和多少个在图层上可拉伸的区域。
暗中同意景况下,contentsCenter是{0,0,壹,壹},那意味若是大小(由contentsGravity决定)改变了,那么寄宿图将会均匀地拉伸。

万一contentsCenter属性是上海体育场所中间的粉红方框,那么当以此图形被拉伸后,contentsCenter属性定义的区域会被周全拉伸(也正是从多个趋势举行推广或收缩),而被这一个方框分隔后的任何方格会遵照上海教室所示的进展横向可能纵向的拉伸,或许有些方框根本不拉伸,那正是contentsCenter属性的意思。

contentsCenter属性和contentsRect属性一样,同样是以比例作为单位。三个属性可以叠加,假若contentsRect属性被设置,contentsCenter属性就会操作contentsRect属性所定义的限量。

下边进入1些代码,基于上个snowman效果,把左下角的六分之一部分举办拉伸

 //左下角四分之一拉伸
 self.layerView.layer.contentsCenter = CGRectMake(0, 0.5, 0.5, 0.5)

也得以在Interface Builder里配置,而不要求写代码

咳嗽的不光是我们刚刚提到的这些标题。事实上,你实在要赋值的门类应该是CGImageRef,它是2个针对性CGImage结构的指针。UIImage有一个CGImage属性,它回到二个”CGImageRef”,假设您想把这一个值直接赋值给CALayer的`contents`,那您将会赢得2个编写翻译错误。因为CGImageRef并不是叁个实在的Cocoa对象,而是四个Core
Foundation类型。

Custom Drawing

为contents赋CGImage值并不是绝无仅有设置寄宿图的措施。咱们也足以直接用Core
Graphics直接绘制寄宿图。

下边通过代码完成CALayerDelegate来绘制图层

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var layerView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()

    // 创建子layer
    let blueLayer = CALayer()
    blueLayer.frame = CGRectMake(50.0, 50.0, 100.0, 100.0)
    blueLayer.backgroundColor = UIColor.blueColor().CGColor

    //设置layer的delegate
    blueLayer.delegate = self

    //确保layer的寄宿图使用正确的scale
    blueLayer.contentsScale = UIScreen.mainScreen().scale

    self.layerView.layer.addSublayer(blueLayer)

    //强制layer重绘
    blueLayer.display()
  }

override func drawLayer(layer: CALayer, inContext ctx: CGContext) {

    CGContextSetLineWidth(ctx, 10.0)

    CGContextSetStrokeColorWithColor(ctx, UIColor.redColor().CGColor)

    CGContextStrokeEllipseInRect(ctx, layer.bounds)
  }
}

注意

  • blueLayer上显示地调用了display()。差别于UIView,当图层展现在显示器上时,CALayer不会自动重绘它的始末,它把重绘的决定权交给了开发者。
  • 即便那里未有设置masksToBound属性,绘制的不行圆依旧沿着边界被压缩了。那是因为当使用CALayerDelegate绘制寄宿图的时候,并未有对超过边界外的情节提供绘制帮助。

终极唯有您创建了3个独门的图层,你大致未有机会用到CALayerDelegate协议。因为当UIView创制了它的寄宿图层时,它会自行地把图层的delegate设置为友好,并提供了叁个displayLayer的落到实处。

示范代码地址

就算Core Foundation类型跟Cocoa对象在运转时相似很像(被称作toll-free
bridging),他们并不是种类包容的,可是你能够由此bridged关键字转换。假使要给图层的寄宿图赋值,你能够遵循以下那一个措施:

“` objective-c

layer.contents = (__bridge id)image.CGImage;

“`

假定你从未应用A陆风X8C(自动引用计数),你就不需求__bridge那部分。但是,你干嘛不用A猎豹CS陆C?!

让我们来继续修改大家在首先章新建的工程,以便能够突显一张图纸而不仅仅是1个背景观。大家已经用代码的点子建立3个图层,那咱们就不必要万分的图层了。那么我们就径直把layerView的宿主图层的`contents`属性设置成图片。

清单二.一更新后的代码。

“` objective-c

@implementation ViewController

– (void)viewDidLoad

{

[super viewDidLoad]; //load an image

UIImage *image = [UIImage imageNamed:@”Snowman.png”];

//add it directly to our view’s layer

self.layerView.layer.contents = (__bridge id)image.CGImage;

}

@end

“`

图表2.一在UIView的宿主图层中展现一张图片

图片 1

咱俩用这么些总结的代码做了一件很有意思的作业:大家使用CALayer在一个1般的UIView中显得了一张图纸。这不是3个UIImageView,它不是大家平日用来显示图片的方法。通过一直操作图层,大家运用了1部分新的函数,使得UIView越发有趣了。

**contentGravity**

你可能早已注意到了小编们的雪人看起来某个。。。胖==!大家加载的图形并不凑巧是八个方的,为了适应那些视图,它有一丝丝被拉伸了。在利用UIImageView的时候遇到过一样的题材,消除方式就是把`contentMode`性子设置成更适于的值,像这么:

“`objective-c

view.contentMode = UIViewContentModeScaleAspectFit;

“`

以此办法基本和我们境遇的情事的缓解格局已经八9不离10了(你可以试一下:)),不过UIView大部分视觉相关的品质比如`contentMode`,对这一个属性的操作实际是对相应图层的操作。

CALayer与`contentMode`对应的性质叫做`contentsGravity`,可是它是贰个NSString类型,而不是像对应的UIKit部分,那里面包车型大巴值是枚举。`contentsGravity`可选的常量值有以下部分:

* kCAGravityCenter

* kCAGravityTop

* kCAGravityBottom

* kCAGravityLeft

* kCAGravityRight

* kCAGravityTopLeft

* kCAGravityTopRight

* kCAGravityBottomLeft

* kCAGravityBottomRight

* kCAGravityResize

* kCAGravityResizeAspect

* kCAGravityResizeAspectFill

和`cotentMode`一样,`contentsGravity`的目标是为了操纵内容在图层的分界中怎么对齐,大家将应用kCAGravityResizeAspect,它的功力1样UIViewContentModeScaleAspectFit,同时它还可以够在图层中等比例拉伸以适应图层的疆界。

“`objective-c

self.layerView.layer.contentsGravity = kCAGravityResizeAspect;

“`

图二.贰方可观察结果

图片 2

图2.贰不错地安装`contentsGravity`的值

##contentsScale

`contentsScale`属性定义了寄宿图的像素尺寸和视图大小的百分比,暗中同意意况下它是3个值为壹.0的浮点数。

`contentsScale`的目标并不是那么强烈。它并不是总会对荧屏上的寄宿图有震慑。假如你品尝对大家的事例设置不一样的值,你就会发现从来没任何影响。因为`contents`由于设置了`contentsGravity`本性,所以它曾经被拉伸以适应图层的边际。

设若你只是单独地想放大图层的`contents`图形,你可以经过行使图层的`transform`和`affineTransform`属性来达到那个目标(见第4章『Transforms』,里面对此有表达),那(指放大)也不是`contengsScale`的指标所在.

`contentsScale`品质其实属于支持高分辨率(又称Hi-DPI或Retina)荧屏机制的一片段。它用来判定在绘制图层的时候理应为寄宿图创立的空中尺寸,和内需展现的图纸的拉伸度(假使并未设置`contentsGravity`属性)。UIView有三个近乎意义但是相当少用到的`contentScaleFactor`属性。

如果`contentsScale`安装为一.0,将会以各样点三个像素绘制图片,假诺设置为贰.0,则会以每一种点2个像素绘制图片,那正是我们熟悉的Retina屏幕。(假若您对像素和点的定义不是很清楚的话,那么些章节的尾部将会对此做出表明)。

这并不会对我们在采用kCAGravityResizeAspect时发出任何影响,因为它正是拉伸图片以适应图层而已,根本不会思虑到分辨率难点。不过壹旦大家把`contentsGravity`设置为kCAGravityCenter(那么些值并不会拉伸图片),那将会有很显著的更动(如图二.三)

图片 3

图二.三用错误的`contentsScale`品质突显Retina图片

如你所见,我们的雪人不仅有点大还有点像素的颗粒感。那是因为和UIImage分化,CGImage未有拉伸的定义。当我们应用UIImage类去读取大家的雪人图片的时候,他读取了高品质的Retina版本的图形。不过当大家用CGImage来设置大家的图层的内容时,拉伸那一个因素在转换的时候就不见了。可是大家得以因而手动设置`contentsScale`来修复这几个标题(如二.贰清单),图贰.四是结果

“`objective-c

@implementation ViewController

– (void)viewDidLoad

{

[super viewDidLoad]; //load an image

UIImage *image = [UIImage imageNamed:@”Snowman.png”]; //add it
directly to our view’s layer

self.layerView.layer.contents = (__bridge id)image.CGImage; //center
the image

self.layerView.layer.contentsGravity = kCAGravityCenter;

//set the contentsScale to match image

self.layerView.layer.contentsScale = image.scale;

}

@end

“`

图片 4

图贰.四相同的Retina图片设置了正确的`contentsScale`之后

当用代码的章程来拍卖寄宿图的时候,一定要切记要手动的设置图层的`contentsScale`属性,不然,你的图片在Retina设备上就展现得不正确啦。代码如下:

“`objective-c

layer.contentsScale = [UIScreen mainScreen].scale;

“`

##maskToBounds

近期大家的雪人总算是体现了天经地义的高低,可是你大概已经意识了此外一些事务:他不止了视图的分界。暗中认可情形下,UIView仍旧会绘制当先界限的始末恐怕子视图,在CALayer下也是这样的。

UIView有多少个叫做`clipsToBounds`的性质能够用来支配是或不是出示超越边界的内容,CALayer对应的特性叫做`masksToBounds`,把它设置为YES,雪人就在边界里啦~(如图二.5)

图片 5

图2.5使用`masksToBounds`来建造图层内容

##contentsRect

CALayer的`contentsRect`天性允许大家在图层边框里显示寄宿图的一个子域。那关系到图片是何许彰显和拉伸的,所以要比`contentsGravity`利落多了

和`bounds`,`frame`不同,`contentsRect`不是按点来计算的,它利用了*单位坐标*,单位坐标钦命在0到一之间,是三个相对值(像素和点正是相对值)。所以她们是相对与寄宿图的尺码的。iOS使用了以下的坐标体系:

*点——在iOS和Mac
OS中最广大的坐标种类。点就像虚拟的像素,也被称作逻辑像素。在规范配备上,1个点便是2个像素,不过在Retina设备上,3个点等于2*1个像素。iOS用点作为荧屏的坐标测算类别正是为了在Retina设备和壹般设备上能有同样的视觉效果。

*像素——物理像素坐标并不会用来显示器布局,但是照旧与图片有相对关系。UIImage是三个荧屏分辨率解决方案,所以钦命点来衡量尺寸。可是有的平底的图纸表示如CGImage就会利用像素,所以你要了然在Retina设备和日常设备上,他们表现出来了不相同的大小。

*单位——对于与图片大小或是图层边界相关的显示,单位坐标是贰个有利的心胸格局,当大小改变的时候,也不须要重新调整。单位坐标在OpenGL这种纹理坐标种类中用得很多,Core
Animation中也采取了单位坐标。

默认的`contentsRect`是{0, 0, 一,
1},那代表全体寄宿图暗许都以可知的,假若大家内定叁个小一些的矩形,图片就会被裁剪(如图贰.陆)

图片 6

图二.6十一个自定义的`contentsRect`(左)和事先展示的剧情(右)

骨子里给`contentsRect`安装2个负数的原点或是大于{1,
一}的尺寸也是能够的。那种境况下,最外面包车型大巴像素会被拉伸以填充剩下的区域。

`contentsRect`在app中最有趣的地点在于一个称作*image
sprites*(图片拼合)的用法。借使您有打闹编制程序的阅历,那么你势必对图片拼合的概念很熟悉,图片可以在显示屏上独立地转移地点。抛开游戏编制程序不谈,那么些技能常用来代替载入拼合的图纸,跟移动图片一点关联也从没。

典型地,图片拼合后方可打包整合到一张大图上一遍性载入。相比较多次载入不一样的图纸,那样做力所能及带来诸多地点的利益:内存使用,载入时间,渲染质量等等

二D游戏引擎入Cocos二D使用了拼合技术,它使用OpenGL来展现图片。然而大家得以选拔拼合在三个一般性的UIKit应用中,对!正是采纳`contentsRect`

先是,大家需求3个拼合后的图形——三个分包小部分的拼合图的大图片。如图2.七所示:

图片 7

接下去,大家要在app中载入并出示那些拼合图。规则相当粗略:像日常壹样载入大家的大图,然后把它赋值给七个独立的图层的`contents`,然后设置每一个图层的`contentsRect`来去掉我们不想显示的某个。

我们的工程中必要某个外加的视图。(为了防止太多代码。我们将动用Interface
Builder来拜访他们的职责,借使你愿意还可以够用代码的点子来贯彻的)。清单二.叁有亟待的代码,图二.8展现了结果

“`objective-c

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *coneView;

@property (nonatomic, weak) IBOutlet UIView *shipView;

@property (nonatomic, weak) IBOutlet UIView *iglooView;

@property (nonatomic, weak) IBOutlet UIView *anchorView;

@end

@implementation ViewController

– (void)addSpriteImage:(UIImage *)image withContentRect:(CGRect)rect
toLayer:(CALayer *)layer //set image

{

layer.contents = (__bridge id)image.CGImage;

//scale contents to fit

layer.contentsGravity = kCAGravityResizeAspect;

//set contentsRect

layer.contentsRect = rect;

}

– (void)viewDidLoad

{

[super viewDidLoad]; //load sprite sheet

UIImage *image = [UIImage imageNamed:@”Sprites.png”];

//set igloo sprite

[self addSpriteImage:image withContentRect:CGRectMake(0, 0, 0.5, 0.5)
toLayer:self.iglooView.layer];

//set cone sprite

[self addSpriteImage:image withContentRect:CGRectMake(0.5, 0, 0.5, 0.5)
toLayer:self.coneView.layer];

//set anchor sprite

[self addSpriteImage:image withContentRect:CGRectMake(0, 0.5, 0.5, 0.5)
toLayer:self.anchorView.layer];

//set spaceship sprite

[self addSpriteImage:image withContentRect:CGRectMake(0.5, 0.5, 0.5,
0.5) toLayer:self.shipView.layer];

}

@end

“`

图片 8

拼合不仅给app提供了三个清洁的载入格局,还使得地拉长了载入质量(单张大图比多张小图载入地越来越快),可是只要有手动布置的话,他们依然有部分不方便人民群众的,假如您必要在一个曾经创办好的品和图上做一些尺码上的改动可能其余改动,无疑是相比费劲的。

Mac上有1些商业软件能够为你活动拼合图片,那么些工具自动生成3个分包拼合后的坐标的XML也许plist文件,拼合图片的利用大大简化。这么些文件能够和图纸一同载入,并给各种拼合的图层设置`contentsRect`,那样开发者就绝不手动写代码来摆放地方了。

这个文件1般在OpenGL游戏中运用,可是呢,你若是有趣味在壹些普遍的app中动用拼合技术,那么三个叫作LayerPepsi-Colas的开源库([https://github.com/nicklockwood/LayerSprites\](https://github.com/nicklockwood/LayerSprites)),它能够读取Cocos2D格式中的拼合图并在普通的Core
Animation层中显得出来。

##contentsCenter

本章咱们介绍的最后贰个和情节有关的天性是`contentsCenter`,看名字你只怕会觉得它恐怕跟图片的地点有关,不过这名字真个误导了你。`contentsCenter`实质上是一个CGRect,它定义了二个定位的边框和一个在图层上可拉伸的区域。改变`contentsCenter`的值并不会影响到寄宿图的展示,除非这一个图层的轻重改变了,你才看获得效果。

私下认可情形下,`contentsCenter`是{0, 0, 一,
1},那表示一旦大小(由`conttensGravity`决定)改变了,那么寄宿图将会均匀地拉伸开。可是倘使大家扩充原点的值并减小尺寸。大家会在图纸的四周创设1个边框。图二.九体现了`contentsCenter`设置为{0.25,
0.25, 0.5, 0.5}的效果。

图片 9

图2.9 `contentsCenter`的例子

那代表大家能够随便重设尺寸,边框依然会是接2连3的。他干活起来的机能和UIImage里的-resizableImageWithCapInsets:方法效果十分接近,只是它可以利用到别的寄宿图,甚至包罗在Core
Graphics运维时绘制的图纸(本章稍后会讲到)。

图片 10

图二.十同等图片接纳不一致的`contentsCenter`

清单2.4示范了什么样编写那么些可拉伸视图。可是,contentsCenter的另1个很酷的特征正是,它可以在Interface
Builder里面配置,根本无须写代码。如图2.11

清单2.4用`contentsCenter`安装可拉伸视图

“`objective-c

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *button1;

@property (nonatomic, weak) IBOutlet UIView *button2;

@end

@implementation ViewController

– (void)addStretchableImage:(UIImage *)image
withContentCenter:(CGRect)rect toLayer:(CALayer *)layer

{

//set image

layer.contents = (__bridge id)image.CGImage;

//set contentsCenter

layer.contentsCenter = rect;

}

– (void)viewDidLoad

{

[super viewDidLoad]; //load button image

UIImage *image = [UIImage imageNamed:@”Button.png”];

//set button 1

[self addStretchableImage:image withContentCenter:CGRectMake(0.25,
0.25, 0.5, 0.5) toLayer:self.button1.layer];

//set button 2

[self addStretchableImage:image withContentCenter:CGRectMake(0.25,
0.25, 0.5, 0.5) toLayer:self.button2.layer];

}

@end

“`

图片 11

图贰.1一用Interface Builder探测窗口控制`contentsCenter`属性

##Custome Drawing

给`contents`赋CGImage的值不是绝无仅有的安装寄宿图的章程。大家也得以直接用Core
Graphics直接绘制寄宿图。能够由此继承UIView并促成`-drawRect:`办法来自定义绘制。

`-drawRect:`格局没有暗中同意的兑现,因为对UIView来说,寄宿图并不是必须的,它不在意那毕竟是干燥的颜色依旧有五个图片的实例。假使UIView检查测试到`-drawRect:`格局被调用了,它就会为视图分配2个寄宿图,这些寄宿图的像素尺寸等于视图大小乘以`contentsScale`的值。

假诺您不要求寄宿图,这就绝不创造这么些办法了,那会造成CPU能源和内部存款和储蓄器的荒废,那也是为何苹果提议:假若未有自定义绘制的职务就无须在子类中写贰个空的-drawRect:方法。

当视图在显示屏上冒出的时候`-drawRect:`措施就会被活动调用。`-drawRect:`办法里面包车型大巴代码应用Core
Graphics去绘制2个寄宿图,然后内容就会被缓存起来直到它要求被更新(日常是因为开发者调用了`-setNeedsDisplay`办法,就算影响到表现效果的属性值被改成时,一些视图类型会被机关重绘,如`bounds`属性)。虽然`-drawRect:`格局是2个UIView方法,事实上都以底层的CALayer安顿了重绘工作和封存了于是发生的图纸。

CALayer有3个可选的`delegate`属性,实现了`CALayerDelegate`协议,当CALayer需求1个内容特定的新闻时,就会从事商业业事务中呼吁。CALayerDelegate是3个业余磋商,其实正是未有CALayerDelegate
@protocol能够让你在类里面引用啦。你只必要调用你想调用的措施,CALayer会帮您做多余的。(`delegate`属性被声称为id类型,全数的代理方法都以可选的)。

当须求被重绘时,CALayer会请求它的代理给他二个寄宿图来显示。它通过调用上边那个方法成功的:

“`objective-c

(void)displayLayer:(CALayerCALayer *)layer;

“`

趁着那个时机,假设代理想一直设置`contents`天性的话,它就能够那样做,否则未有别的办法能够调用了。即使代理不落实`-displayLayer:`艺术,CALayer就会转而品尝调用下边那几个艺术:

“`objective-c

– (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

“`

在调用那么些方法此前,CALayer创造了2个拾1分尺寸的空寄宿图(尺寸由`bounds`和`contentsScale`支配)和贰个Core
Graphics的绘图上下文环境,为绘制寄宿图做准备,他作为ctx参数传入。

让大家来持续第一章的类型让它达成CALayerDelegate并做壹些绘制工作啊(见清单二.伍).图贰.1二是她的结果

清单2.5实现CALayerDelegate

“`objective-c

@implementation ViewController

– (void)viewDidLoad

{

[super viewDidLoad];

//create sublayer

CALayer *blueLayer = [CALayer layer];

blueLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);

blueLayer.backgroundColor = [UIColor blueColor].CGColor;

//set controller as layer delegate

blueLayer.delegate = self;

//ensure that layer backing image uses correct scale

blueLayer.contentsScale = [UIScreen mainScreen].scale; //add layer to
our view

[self.layerView.layer addSublayer:blueLayer];

//force layer to redraw

[blueLayer display];

}

– (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

{

//draw a thick red circle

CGContextSetLineWidth(ctx, 10.0f);

CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);

CGContextStrokeEllipseInRect(ctx, layer.bounds);

}

@end

“`

图片 12

图二.12落到实处CALayerDelegate来绘制图层

留意一下有的妙不可言的事情:

*咱俩在blueLayer上显式地调用了`-display`。分裂于UIView,当图层展现在显示器上时,CALayer不会自动重绘它的始末。它把重绘的决定权交给了开发者。

*即便大家未有用`masksToBounds`品质,绘制的要命圆如故沿边界被裁剪了。那是因为当您使用CALayerDelegate绘制寄宿图的时候,并不曾对超越边界外的剧情提供绘制补助。

于今您明白了CALayerDelegate,并通晓怎么利用它。可是唯有您创设了一个独门的图层,你差不离未有机会用到CALayerDelegate协议。因为当UIView成立了它的宿主图层时,它就会自行地把图层的delegate设置为它自个儿,并提供了二个`-displayLayer:`的贯彻,这全部的标题就都没了。

当使用寄宿了视图的图层的时候,你也不必完毕`-displayLayer:`和`-drawLayer:inContext:`办法来绘制你的寄宿图。平时做法是促成UIView的`-drawRect:`艺术,UIView就会帮你做完剩余的干活,包蕴在急需重绘的时候调用`-display`方法。

##总结

本章介绍了寄宿图和有些有关的习性。你学到了怎么样显示和停放图片,使用拼合技术来显示,以及用CALayerDelegate和Core
Graphics来绘制图层内容。

在第三章,”图层几何学”中,大家将会追究一下图层的几何,观看他们是怎么着放置和转移互相的尺码的。

转载:http://blog.csdn.net/huangznian/article/details/42741283