iOS Core Animation--寄宿图

    xiaoxiao2021-03-25  14

    一、寄宿图–contents属性 (1) CALayer有一个属性叫contents,contents默认可以传一个id类型的对象,但是只有你传CGImage的时候,它才能够正常显示在屏幕上。所以最终我们的图形渲染落点落在contents身上如图。

    注意:如果你想将UIImage类型的图赋值给contents,你可以使用下面的方法: layer.contents = (__bridge id)image.CGImage; ( 解释:因为,我们赋值的类型是CGImageRef,它是指向CGImage指针,UIImage有一个CGImage属性,它返回CGImageRef类型,但直接将其赋值给CAlayer的contents会出错,因为CGImageRef是属于Core Foundation类型,应使用Bridge) 例如:

    //给view设置一张图片—方法是操作图层添加图片 UIImage *image = [UIImage imageNamed:@"w.jpg"]; view.layer.contents = (__bridge id)(image.CGImage);

    (2)设置图层内容的几个属性 contentsGravity:设置内容在图层边界怎样对齐; 如果是等比例拉伸图片使用UIViewContentModeScaleAspectFit。UIView大多数与视觉相关的属性比如contentMode,对这些视觉属性的操作其实是对图层的操作;图层的contentsGravity是与contentMode对应的属性,它是NSString类型。

    contentsScale:定义了寄宿图的像素尺寸和视图大小的比例,默认为1.0;其实该属性是支持高分辨机制的一部分,用来判断在绘制图层的时候应该为寄宿图创建空间的大小和需要显示的图片的拉伸度。对应的UIView有一个很少用到的属性是contentScaleFactor(如果值为1.0,将会以每个点1像素绘制图片;如果为2.0,将会以每个点2像素绘制图片,就是Retina屏)

    注意:conentsScale属性受contentsGravity的影响。如果设置contentsGravity,表示图片已被拉伸;此时设置图层的contentsScale会没有任何影响

    makeToBounds:用于决定是否沿边界裁剪只显示边框中的内容,YES表示只显示边界内的图片,UIView对应的属性是clipsToBounds

    contentsRect:用于显示图层的寄宿图的一个子域,默认为{0,0,1,1},显示全部寄宿图;

    注意:contentsRect使用的是单位坐标,单位坐标指定在0~1之间,是相对值。下面是点、像素、单位的介绍

    contentsCenter:它是CGRect类型,定义了一个固定的边框和一个在图层上可拉伸的区域。默认contentsCenter是{0,0,1,1},这意味着如果大小(由contentsGravity)改变了,寄宿图将会均匀的拉伸开。他的效果和UIImage中的-resizableImageWithCapInsets:方法类似。

    下面是我们增加原点值并减小尺寸的效果

    二、自定义绘制图层Custom Drawing

    当视图出现在屏幕上的时候,-drawRect:是被自动调用的。-drawRect:中的代码利用Core Graphics绘制寄宿图,然后将内容缓存起来用于以后的更新。所以虽然-drawRect:是UIView的方法,但是实际上底层的CALayer进行重绘工作,然后保存产生的图片

    使用Core Graphics直接绘制寄宿图,通过继承UIView并实现-drawRect:方法来自定义绘制。一旦UIView中检测到重写了-drawRect:方法,UIView就会为视图分配一个寄宿图,寄宿图的像素尺寸=视图大小*contentsScale的值; 所以不需要寄宿图,尽量不要重写-drawRect:方法,因为给它分配寄宿图会大量消耗CPU资源和内存的。

    CALayer有一个可选的delegate属性,实现CALayerDelegate协议,但是这个协议是非正式协议,即没有CALayerDelegate @protocol可以让我们引用。我们只需调用我们想调用的方法,剩下的CALayer会处理。但一般UIVIew创建宿主图层之后,就会将图层的delegate设置为他自己。提供一个dispayerLayer:的实现。

    需要重绘时调用-(void)displayLayer:(CALayerCALayer *)layer; CALayer会请求他的代理给它一个寄宿图,在这个方法中代理可以设置contents属性

    如果没有实现-displayLayer:方法,CALayer会创建空的寄宿图和一个Core Graphics的绘制上下文环境作为ctx参数传入;然后,调用 -(void)drawLayer:(CALayer *)layer inContext:(CGContexRef)ctx;

    但实际使用时,一般使用寄宿了视图的图层,不必实现-displayLayer:和-drawLayer:inContext:方法绘制寄宿图。通常实现UIView的-drawRect:方法,其他的UIView会包揽全部工作

    注意:(1)当图层显示在屏幕上时,CALayer不会自动重绘,而是由开发者决定绘制,通过调用-display函数开始重回 (2)没使用masksToBounds,图形也会沿边界裁剪,因为CALayerDelegate没有对超出边界外的内容提供绘制支持

    - (void)viewDidLoad { [super viewDidLoad]; //创建子图层 CALayer *blueLayer = [CALayer layer]; blueLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f); blueLayer.backgroundColor = [UIColor blueColor].CGColor; //设置controller为layer的代理 blueLayer.delegate = self; //确保背景图片的图层使用正确的scale blueLayer.contentsScale = [UIScreen mainScreen].scale; [self.view.layer addSublayer:blueLayer]; //强制重画图层,当图层显示在屏幕上时,CALyer不会自动重绘,而是由开发者决定绘制 [blueLayer display]; } -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{ //画一个红色的圆 CGContextSetLineWidth(ctx, 10); CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor); //在指定区域画一个椭圆,并充满这个空间 CGContextStrokeEllipseInRect(ctx, layer.frame); }
    转载请注明原文地址: https://ju.6miu.com/read-149653.html

    最新回复(0)