学习动画总结——寄宿图

CALayer——寄宿图

CALayer类在概念上和UIView类似,同样也是一些被层级关系树管理的矩形块,同样也可以包含一些内容(像图片,文本或者背景色),管理子图层的位置。它们有一些方法和属性用来做动画和变换。和UIView最大的不同是CALayer不处理用户的交互。
这里有一些UIView没有暴露出来的CALayer的功能:
阴影,圆角,带颜色的边框,3D变换,非矩形范围,透明遮罩,多级非线性动画
首先,使用layer写一个简单的效果

    UIView *temp = [[UIView alloc]initWithFrame:CGRectMake(50, 100, 300, 400)];
    [self.view addSubview:temp];
    temp.backgroundColor = [UIColor blueColor];

    CALayer * layer = [CALayer layer];
    layer.frame = CGRectMake(50, 50 , 20, 20);
    layer.backgroundColor = [UIColor yellowColor].CGColor;
    [temp.layer addSublayer:layer];

也可以实现一个view只有上下边框,只要将宽度设置成1 就好了

contents属性
显示完色块,也可以显示图片,运用CALayer 有一个属性叫做contents,这个属性的类型被定义为id,意味着它可以是任何类型的对象。在这种情况下,你可以给contents属性赋任何值,你的app仍然能够编译通过。但是,在实践中,如果你给contents赋的不是CGImage,那么你得到的图层将是空白的。事实上,你真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针。UIImage有一个CGImage属性,它返回一个”CGImageRef”,如果你想把这个值直接赋值给CALayer的contents,那你将会得到一个编译错误,可以通过bridged关键字转换。如果要给图层的寄宿图赋值,你可以按照以下这个方法

    UIImage *image = [UIImage imageNamed:@"1.png"];
    temp.layer.contents = (__bridge id _Nullable)(image.CGImage);

图片

如果感觉图片有拉伸 可以添加contentMode属性,将图片进行调整

    temp.contentMode = UIViewContentModeScaleAspectFit;

contentsScale属性
contentsScale属性定义了寄宿图的像素尺寸和视图大小的比例,默认情况下它是一个值为1.0的浮点数。
前提,如果设置了contentMode属性,那么contentsScale就会没有效果,因为它已经被拉伸以适应图层的边界。如果你只是单纯地想放大图层的contents图片,你可以通过使用图层的transform和affineTransform属性来达到这个目的。
当用代码的方式来处理寄宿图的时候,一定要记住要手动的设置图层的contentsScale属性,否则,你的图片在Retina设备上就显示得不正确啦。代码如下:

    temp.layer.contentsScale = [UIScreen mainScreen].scale;

maskToBounds属性
masksToBounds属性可以用来决定是否显示超出边界的内容,把它设置为YES,

contentsRect属性
CALayer的contentsRect属性允许我们在图层边框里显示寄宿图的一个子域。contentsRect不是按点来计算的,它使用了单位坐标,单位坐标指定在0到1之间,是一个相对值(像素和点就是绝对值)。所以他们是相对与寄宿图的尺寸的。默认的contentsRect是{0, 0, 1, 1},这意味着整个寄宿图默认都是可见的,如果我们指定一个小一点的矩形,图片就会被裁剪。

    temp.layer.contentsRect = CGRectMake(0, 0, 0.5, 0.5);

这里写图片描述

事实上给contentsRect设置一个负数的原点或是大于{1, 1}的尺寸也是可以的。这种情况下,最外面的像素会被拉伸以填充剩下的区域。

contentsCenter属性
contentsCenter其实是一个CGRect,它定义了一个固定的边框和一个在图层上可拉伸的区域。 改变contentsCenter的值并不会影响到寄宿图的显示,除非这个图层的大小改变了,你才看得到效果。默认情况下,contentsCenter是{0, 0, 1, 1},

    temp.layer.contentsCenter = CGRectMake(0.5, 0.5, 0.2, 0.2);

中间的变化

找到一个讲解的图片不错

这意味着我们可以随意重设尺寸,边框仍然会是连续的。他工作起来的效果和UIImage里的-resizableImageWithCapInsets: 方法效果非常类似
contentsCenter可以在xib中设置!

Custome Drawing属性
contents不是唯一的方法,也能够通过继承UIView并实现-drawRect:方法来自定义绘制。当视图在屏幕上出现的时候 -drawRect:方法就会被自动调用。-drawRect:方法里面的代码利用Core Graphics去绘制一个寄宿图,然后内容就会被缓存起来直到它需要被更新(通常是因为开发者调用了-setNeedsDisplay方法,尽管影响到表现效果的属性值被更改时,一些视图类型会被自动重绘,如bounds属性)。虽然-drawRect:方法是一个UIView方法,事实上都是底层的CALayer安排了重绘工作和保存了因此产生的图片。
CALayer有一个可选的delegate属性,实现了CALayerDelegate协议,当CALayer需要一个内容特定的信息时,就会从协议中请求。CALayerDelegate是一个非正式协议,其实就是说没有CALayerDelegate @protocol可以让你在类里面引用啦。你只需要调用你想调用的方法,CALayer会帮你做剩下的。(delegate属性被声明为id类型,所有的代理方法都是可选的)。
当需要被重绘时,CALayer会请求它的代理给他一个寄宿图来显示。它通过调用 (void)displayLayer:(CALayerCALayer )layer 做到的。趁着这个机会,如果代理想直接设置contents属性的话,它就可以这么做,不然没有别的方法可以调用了。如果代理不实现-displayLayer:方法,CALayer就会转而尝试调用 - (void)drawLayer:(CALayer )layer inContext:(CGContextRef)ctx 方法

    layer.delegate = self;
    [layer display];//调用方法必须写

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGContextSetLineWidth(ctx, 10.f);
    CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextStrokeEllipseInRect(ctx, layer.bounds);
}

这里写图片描述

注意:
1.在Layer上显式地调用了-display。不同于UIView,当图层显示在屏幕上时,CALayer不会自动重绘它的内容。它把重绘的决定权交给了开发者。
2.尽管没有用masksToBounds属性,绘制的那个圆仍然沿边界被裁剪了。这是因为当你使用CALayerDelegate绘制寄宿图的时候,并没有对超出边界外的内容提供绘制支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值