CoreAnimation 寄宿图
CoreAnimation 寄宿图
博客园makedown支持不佳,如有需要请进GitHub.
寄宿图:图层中所包含的图 by:旭宝爱吃鱼
针对于寄宿图我在这里只讨论contents属性以及Custom Drawing.
contents
content:内容
CALayer的contents
属性是一个id
类型.
@property(nullable, strong) id contents;
因此,可以将任何类型的对象赋值给contents
,但是如果将非CGImage类型的对象赋值给contents
将会的到一个空白页.contents
之所以会存在这种现象是因为Mac OS的历史原因造成的.
原因: contents
对CGImage类型的对象以及NSImage类型的对象都起作用!
然而问题并不是只有这么一点点,我们可以尝试将UIImage的CGImage赋值给contents
,不幸的是将会得到一个编译报错,产生错误的原因是CGImage返回的CGImageRef并不是一个Cocoa对象而是CoreFoundation类型,这时我们需要用bridged关键字进行转换(MRC下不需要).
layer.contents = (__bridge id)image.CGImage;
下面我们把一张图片赋值给contents
.
为了便于对比我将原图粘贴于此
- (void)viewDidLoad {
[super viewDidLoad];
UIImage * layerImage = [UIImage imageNamed:@"goddess"];
// 在图层上添加图片
self.customView.layer.contents = (__bridge id)layerImage.CGImage;// 图片一
}
展示效果如下:
通过两行代码我们将GODDESS添加到图层之上,但是与原图相比我们发现goddess变胖了许多,我们不希望见到这中效果,因此我们需要对contentGravity
属性进行设置.
contentGravity
contentGravity:图层的展示类型.
CALayer的contentsGravity
属性是一个NSString
类型.
@property(copy) NSString *contentsGravity;
contentsGravity
并没有采取枚举类型的赋值方式,因此我在这里列出其相应的赋值范围.
- kCAGravityCenter
- kCAGravityTop
- kCAGravityBottom
- kCAGravityLeft
- kCAGravityRight
- kCAGravityTopLeft
- kCAGravityTopRight
- kCAGravityBottomLeft
- kCAGravityBottomRight
- kCAGravityResize
- kCAGravityResizeAspect
- kCAGravityResizeAspectFill
为了改变上面结果的缺陷我们添加以下代码:
layer.contentsGravity = kCAGravityResizeAspect;
得到以下效果:
contentsScale
contentsScale:像素尺寸与试图大小的比例(默认1.0).
contentsScale
属性是为了适配高分辨的屏幕机制,如果我们将其设置为1.0我们的得到的便是一个点由两个像素组成,如果将其设置为2.0我们得到的便是一个点由两个像素组成.
一般状态下我们设置的方式如下:
layer.contentsScale = [UIScreen mainScreen].scale;
注意:
当我们能设置contentsGravity
自动拉伸类状态时,设置contentsScale
是没有效果的,因为contentsGravity
已经对图层的展示进项了拉伸适配,如果我们需要查看设置contentsScale
的效果我们可以将contentsGravity
设置为kCAGravityCenter;
maskToBounds
maskToBounds:
YES(不展示图层以外的内容)
NO(展示图层以外的内容)
代码示例:
layer. maskToBounds = YES;
iOS视图默认允许我们将一个尺寸较大的图层添加到一个尺寸较小的图层上并加以展示,但是此时处于父图层以外的子图层区域的点击等交互事件是监听不到的,以及其他展示效果的影响我们在许多非正常布局的情况下我们需要将maskToBounds
设置为YES.或者UIView的clipsToBounds
属性设置为YES.
contentsRect
contentsRect:允许在图层范围内显示寄宿图的一个子域.
{x,y,w,h} 四个参数的取值范围是0~1.
默认状态下contentsRect
的取值是{0,0,1,1},也就是默认状态下是显示整个寄宿图,也就是如下图的效果.
如我我们将contentsRect
的取值设置为{0.5, 0.5, 0.5, 0.5},效果就变成如下图所示:
在app中contentsRect比较典型的用法就是图片拼合用法,也就是我们所需要展示的许多内容都在一张Image上,但是展示时通过contentsRect我们将他们一一取出,这样就极大的节约了内存的使用率.
contentsCenter
contentsCenter:并不是contents的中心点,而是定义了一个固定的边框和一个在图层上可拉伸的区域.
contentsCenter
使用效果和UIImage里的-resizableImageWithCapInsets: 方法效果非常类似,但是它可以运用到任何寄宿图,甚至包括在Core Graphics运行时绘制的图形,在这里就不多赘述具体的操作方法.
Custom Drawing
Custom Drawing:自定义绘制.
UIView-drawRect
-drawRect
并不是一个十分陌生的方法,每当我么自定义UIView的时候都可一看到他的身影,他的本身含以也正如我们自定义UIView的意图,我们可以通过他实现自定义绘制寄宿图.
-drawRect:
方法是没有被苹果默认实现的,因为对与UIView来说,寄宿图不是他所必须.如果UIView检测到-drawRect:
方法被实现了,那么UIView会为视图分配一个寄宿图,寄宿图的像素尺寸等于视图大小乘以 contentsScale
的值。需要注意的是如果我们不需要使用寄宿图我们不要实现-drawRect:
,因为这会造成CPU以及内存的不必要浪费,当然apple也是这么建议的.
-drawRect:
的调用是在视图出现在屏幕的时候,-drawRect:
利用其封装的代码通过CoreGraphics来绘制一个寄宿图,当寄宿图绘制结束后会被缓存起来,直到它需要更新的时候(通过调用-setNeedsDisplay
)去重新绘制更新.
CALayer-displayLayer:
&&-drawLayer:inContext:
-displayLayer:
对象方法
-drawLayer:inContext:
代理方法
我们可以通过CALayerDelegate
的-drawLayer:inContext:
来实现自定义绘制图层.需要做的内容很简单,设置layer的代理,然后实现-drawLayer:inContext:
方法,当我们需要更新绘制的时候调用-displayLayer:
即可.
注意:
- CALayer不同于UIView,当图层显示在屏幕上时,CALayer不会自动重绘它的内容,它把重绘的决定权交给了开发者。
- 当使用CALayerDelegate绘制寄宿图的时候,并不会对超出边界外的内容进行绘制。