美文网首页程序员
【CALayer】iOS中的图层

【CALayer】iOS中的图层

作者: 大基本功 | 来源:发表于2018-06-05 16:59 被阅读9次

CALayer是什么

  • 在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView ;其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层
  • 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
    @property(nonatomic,readonly,retain) CALayer *layer;
  • 当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示
  • 换句话说,UIView本身不具备显示的功能,是它内部的层才有显示功能
  • CALayer是定义在QuartzCore框架中的(Core Animation);CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的;UIColor、UIImage是定义在UIKit框架中的

UIView和CALayer的选择

  • 通过CALayer,就能做出跟UIView一样的界面效果;既然CALayer和UIView都能实现相同的显示效果,那究竟该选择谁好呢?
  • 其实,对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
  • 所以,如果显示出来的东西需要跟用户进行交互的话,用UIView;如果不需要跟用户进行交互,用UIView或者CALayer都可以;当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级

图层的添加

1️⃣添加一个简单的图层
 1 CALayer *myLayer = [CALayer layer];
 2 // 设置层的宽度和高度(100x100)
 3 myLayer.bounds = CGRectMake(0, 0, 100, 100);
 4 // 设置层的位置
 5 myLayer.position = CGPointMake(100, 100);
 6 // 设置层的背景颜色:红色
 7 myLayer.backgroundColor = [UIColor redColor].CGColor;
 8 // 设置层的圆角半径为10
 9 myLayer.cornerRadius = 10;
10
11 // 添加myLayer到控制器的view的layer中
12 [self.view.layer addSublayer:myLayer];
2️⃣添加一个显示图片的图层
1 CALayer *myLayer = [CALayer layer];
 2 // 设置层的宽度和高度(100x100)
 3 myLayer.bounds = CGRectMake(0, 0, 100, 100);
 4 // 设置层的位置
 5 myLayer.position = CGPointMake(100, 100);
 6 // 设置需要显示的图片
 7 myLayer.contents = (id)[UIImage imageNamed:@"lufy.png"].CGImage;
 8 // 设置层的圆角半径为10
 9 myLayer.cornerRadius = 10;
10 // 如果设置了图片,需要设置这个属性为YES才有圆角效果
11 myLayer.masksToBounds = YES;
12
13 // 添加myLayer到控制器的view的layer中
14 [self.view.layer addSublayer:myLayer];
3️⃣为什么CALayer中使用CGColorRef和CGImageRef这2种数据类型,而不用UIColor和UIImage?
  • 首先要知道:CALayer是定义在QuartzCore框架中的;CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的;UIColor、UIImage是定义在UIKit框架中的
  • 其次,QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用,但是UIKit只能在iOS中使用
  • 因此,为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef
  • 不过很多情况下,可以通过UIKit对象的特定方法,得到CoreGraphics对象,比如UIImage的CGImage方法可以返回一个CGImageRef

UIView和CALayer的其他关系

  • UIView可以通过subviews属性访问所有的子视图,类似地,CALayer也可以通过sublayers属性访问所有的子层
  • UIView可以通过superview属性访问父视图,类似地,CALayer也可以通过superlayer属性访问父层
  • 下面再看一张UIView和CALayer的关系图:



    如果两个UIView是父子关系,那么它们内部的CALayer也是父子关系。

CALayer中的position和anchorPoint属性

  • position和anchorPoint属性都是CGPoint类型的
  • position可以用来设置CALayer在父层中的位置,它是以父层的左上角为坐标原点(0, 0)
  • anchorPoint称为"定位点",它决定着CALayer身上的哪个点会在position属性所指的位置。它的x、y取值范围都是0~1,默认值为(0.5, 0.5)
1.创建一个CALayer,添加到控制器的view的layer中
1 CALayer *myLayer = [CALayer layer];
 2 // 设置层的宽度和高度(100x100)
 3 myLayer.bounds = CGRectMake(0, 0, 100, 100);
 4 // 设置层的位置
 5 myLayer.position = CGPointMake(100, 100);
 6 // 设置层的背景颜色:红色
 7 myLayer.backgroundColor = [UIColor redColor].CGColor;
 8
 9 // 添加myLayer到控制器的view的layer中
10 [self.view.layer addSublayer:myLayer];

第5行设置了myLayer的position为(100, 100),又因为anchorPoint默认是(0.5, 0.5),所以最后的效果是:myLayer的中点会在父层的(100, 100)位置


2.若将anchorPoint改为(0, 0),myLayer的左上角会在(100, 100)位置
3.若将anchorPoint改为(1, 1),myLayer的右下角会在(100, 100)位置
4.将anchorPoint改为(0, 1),myLayer的左下角会在(100, 100)位置

总结anchorPoint的用途:它决定着CALayer身上的哪个点会在position所指定的位置上。它的x、y取值范围都是0~1,默认值为(0.5, 0.5),因此,默认情况下,CALayer的中点会在position所指定的位置上。当anchorPoint为其他值时,以此类推。

自定义层

方法1

1️⃣创建一个CALayer的子类

#import<QuartzCore/QuartzCore.h>
@interface MJLayer:CALayer
@end

2️⃣在.m文件中覆盖drawInContext:方法,在里面绘图

1 @implementation MJLayer
 2
 3 #pragma mark 绘制一个实心三角形
 4 - (void)drawInContext:(CGContextRef)ctx {
 5     // 设置为蓝色
 6     CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);
 7
 8    
 9     // 设置起点
10     CGContextMoveToPoint(ctx, 50, 0);
11     // 从(50, 0)连线到(0, 100)
12     CGContextAddLineToPoint(ctx, 0, 100);
13     // 从(0, 100)连线到(100, 100)
14     CGContextAddLineToPoint(ctx, 100, 100);
15     // 合并路径,连接起点和终点
16     CGContextClosePath(ctx);
17    
18     // 绘制路径
19     CGContextFillPath(ctx);
20 }
21
22 @end

3️⃣在控制器中添加图层到屏幕上

1 MJLayer *layer = [MJLayer layer];
2 // 设置层的宽高
3 layer.bounds = CGRectMake(0, 0, 100, 100);
4 // 设置层的位置
5 layer.position = CGPointMake(100, 100);
6 // 开始绘制图层
7 [layer setNeedsDisplay];
8 [self.view.layer addSublayer:layer];

注意第7行,需要调用setNeedsDisplay这个方法,才会触发drawInContext:方法的调用,然后进行绘图

方法2

方法描述:设置CALayer的delegate,然后让delegate实现drawLayer:inContext:方法,当CALayer需要绘图时,会调用delegate的drawLayer:inContext:方法进行绘图。

  • 这里要注意的是:不能再将某个UIView设置为CALayer的delegate,因为UIView对象已经是它内部根层的delegate,再次设置为其他层的delegate就会出问题。UIView和它内部CALayer的默认关系图:

1️⃣创建新的层,设置delegate,然后添加到控制器的view的layer中

1 CALayer *layer = [CALayer layer];
 2 // 设置delegate
 3 layer.delegate = self;
 4 // 设置层的宽高
 5 layer.bounds = CGRectMake(0, 0, 100, 100);
 6 // 设置层的位置
 7 layer.position = CGPointMake(100, 100);
 8 // 开始绘制图层
 9 [layer setNeedsDisplay];
10 [self.view.layer addSublayer:layer];
  • 在第3行设置了CALayer的delegate,这里的self是指控制器
  • 注意第9行,需要调用setNeedsDisplay这个方法,才会通知delegate进行绘图

2️⃣让CALayer的delegate(前面设置的是控制器)实现drawLayer:inContext:方法

 1 #pragma mark 画一个矩形框
 2 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
 3     // 设置蓝色
 4     CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
 5     // 设置边框宽度
 6     CGContextSetLineWidth(ctx, 10);
 7    
 8     // 添加一个跟层一样大的矩形到路径中
 9     CGContextAddRect(ctx, layer.bounds);
10    
11     // 绘制路径
12     CGContextStrokePath(ctx);
13 }

总结

1️⃣无论采取哪种方法来自定义层,都必须调用CALayer的setNeedsDisplay方法才能正常绘图。
2️⃣UIView的详细显示过程
  • 当UIView需要显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法
  • 平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入层的CGContextRef中,然后被拷贝至屏幕

相关文章

  • CALayer

    初探CALayer属性 IOS中CALayer的使用//这个算是比较全了 iOS - CALayer 绘图层 iO...

  • 【CALayer】iOS中的图层

    CALayer是什么 在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文...

  • iOS 高级核心动画 day01 - 图层树、UIView、CA

    一、图层树(认识 UIView 和 CALayer) 1. iOS 中所有的视图都从哪个视图派生而来? iOS 中...

  • iOS-CALayer之渐变图层

    CAGradientLayer 渐变图层 CALayer子类之一 渐变图层是根据colors数组中的颜色在图层中...

  • 实现按钮的动画效果

    原文链接 ----- sindrilin 在iOS中,每一个UIView都拥有一个与之绑定的CALayer图层对...

  • CALayer

    CALayer 父类是NSObject layer(图层):在iOS中,UIView之所以能显示在屏幕上,完全是因...

  • CALayer图层类

    //CALayer图层类 //和UIView用法类似 //创建图层类对象 // CALayer *layer = ...

  • iOS 图形拉伸变换

    首先在iOS中,CALayer 是UIView 的内容承载,UIView是为图层提供了底层的事件处理,本身更像是一...

  • Quartz2D实现简单“画图板”

    概念: 1.首先要明白所有iOS中见到的所有东西,都是因为通过UIView内部的图层——CALayer对象; 并且...

  • CALayer 和 Core Animation

    CALayer 一、简介 1.CALayer 简单的说是层(图层)的概念,类似与PS中的图层。一个用来完成绘制、渲...

网友评论

    本文标题:【CALayer】iOS中的图层

    本文链接:https://www.haomeiwen.com/subject/labpsftx.html