CALayer的寄宿图

    CALayer 有一个属性叫做contents,它可以直接在图层中放置一张图片

@property contents

     尽管类型被定义为id,赋值CGImage,真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针。

    事实上,contents这个奇怪的表现是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。

    ARC下,要给图层的寄宿图赋值,可以按照以下这个方法:

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


    在我们为视图赋值图片的时候,有时会遇到图片为了适应视图而进行拉伸等改变。解决方法就是把contentMode属性设置成更合适的值,像这样:

       view.contentMode = UIViewContentModeScaleAspectFit;

       CALayer与contentMode对应的属性叫做contentsGravity

@property contentsGravity            

      决定内容在图层的边界对齐方式, NSString 类型,默认值为kCAGravityResize,。

      kCAGravityCenter,水平和垂直居中

      kCAGravityTop,水平居中,垂直置顶边缘

      kCAGravityBottom,水平居中,垂直置底边缘

      kCAGravityLeft,水平居左边缘,垂直居中

      kCAGravityRight,水平居右边缘,垂直居中

      kCAGravityTopLeft,水平居左边缘,垂直置顶边缘   

      kCAGravityTopRight,水平居右边缘,垂直置顶边缘

      kCAGravityBottomLeft,水平居左边缘,垂直置底边缘

      kCAGravityBottomRight,水平居右边缘,垂直置底边缘   

      kCAGravityResize,调整大小以适应整个边界矩形

      kCAGravityResizeAspect,整大小以适应边界矩形,保持内容方面。如果内容不完全填充边 界矩形,则内容集中在部分轴上.

      kCAGravityResizeAspectFill。调整到完全填充边界矩形,同时仍然保留内容方面。内容集中在它超过的轴.


@property contentsScale

      定义了寄宿图的像素尺寸和视图大小的比例,默认情况下它是一个值为1.0的浮点数

      contentsScale属性其实属于支持高分辨率(又称Hi-DPI或Retina)屏幕机制的一部分。它用来判断在绘制图层的时候应该为寄宿图创建的空间大小,和需要显示的图片的拉伸度(假设并没有设置contentsGravity属性)。

      这并不会对我们在使用kCAGravityResizeAspect时产生任何影响,因为它就是拉伸图片以适应图层而已,根本不会考虑到分辨率问题。但是如果我们把contentsGravity设置为kCAGravityCenter(这个值并不会拉伸图片),那将会有很明显的变化.

       当用代码的方式来处理寄宿图的时候,一定要记住要手动的设置图层的contentsScale属性.

        layer.contentsScale = [UIScreen mainScreen].scale;


@property maskToBounds

     默认情况下,UIView仍然会绘制超过边界的内容或是子视图,在CALayer下也是这样的。UIView有一个叫做clipsToBounds的属性可以用来决定是否显示超出边界的内容,CALayer对应的属性叫做masksToBounds.


UIImage *image = [UIImage imageNamed:@"素材"];

//add it directly to our view's layer

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

//正确地设置contentsGravity的值

self.layerView.layer.contentsGravity = kCAGravityCenter;

//set the contentsScale to match image

self.layerView.layer.contentsScale = [UIScreen mainScreen].scale;;

// 使用masksToBounds来修建图层内容

self.layerView.layer.masksToBounds = YES;



@property contentsRect

    CALayer的contentsRect属性允许我们在图层边框里显示寄宿图的一个子域,contentsRect不是按点来计算的,它使用了单位坐标,单位坐标指定在0到1之间,是一个相对值(像素和点就是绝对值)。所以他们是相对与寄宿图的尺寸的,默认的contentsRect是{0, 0, 1, 1}.

iOS使用了以下的坐标系统:

点 —— 在iOS和Mac OS中最常见的坐标体系。点就像是虚拟的像素,也被称作逻辑像素。在标准设备上,一个点就是一个像素,但是在Retina设备上,一个点等于2*2个像素。iOS用点作为屏幕的坐标测算体系就是为了在Retina设备和普通设备上能有一致的视觉效果。

像素 —— 物理像素坐标并不会用来屏幕布局,但是仍然与图片有相对关系。UIImage是一个屏幕分辨率解决方案,所以指定点来度量大小。但是一些底层的图片表示如CGImage就会使用像素,所以你要清楚在Retina设备和普通设备上,他们表现出来了不同的大小。

单位 —— 对于与图片大小或是图层边界相关的显示,单位坐标是一个方便的度量方式, 当大小改变的时候,也不需要再次调整。单位坐标在OpenGL这种纹理坐标系统中用得很多,Core Animation中也用到了单位坐标。

       contentsRect在app中最有趣的地方在于一个叫做image sprites(图片拼合)的用法。这个技术常用来指代载入拼合的图片,跟移动图片一点关系也没有。不过呢,你要是有兴趣在一些常见的app中使用拼合技术,那么一个叫做LayerSprites的开源库(https://github.com/nicklockwood/LayerSprites),它能够读取Cocos2D格式中的拼合图并在普通的Core Animation层中显示出来。



CALayer的寄宿图_第1张图片

#pragma mark - 3.图片拼合

- (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)imageSprites{

UIImage *image = [UIImage imageNamed:@"2.7"];

//set igloo sprite

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

//set cone sprite

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

//set anchor sprite

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

//set spaceship sprite

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

}


CALayer的寄宿图_第2张图片


@property contentsCenter

      contentsCenter其实是一个CGRect,它定义了一个固定的边框和一个在图层上可拉伸的区域。

      默认情况下,contentsCenter是{0, 0, 1, 1},如果大小(由conttensGravity决定)改变了,那么寄宿图将会均匀地拉伸开。

      如果我们增加原点的值并减小尺寸。我们会在图片的周围创造一个边框。

CALayer的寄宿图_第3张图片
可以随意重设尺寸,边框仍然会是连续的。他工作起来的效果和UIImage里的-resizableImageWithCapInsets: 方法效果非常类似,只是它可以运用到任何寄宿图,甚至包括在Core Graphics运行时绘制的图形.

    contentsCenter可以在Interface Builder里面配置.


CALayer的寄宿图_第4张图片

#pragma mark - 设置可拉伸视图

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

{

//set image

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

//set contentsCenter

layer.contentsCenter = rect;

}

- (void)setStretchableImage{

UIImage *image = [UIImage imageNamed:@"素材"];

//set button 1

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

//set button 2

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

}



你可能感兴趣的:(CALayer的寄宿图)