CALayer 图层

概念

  1. CA -> Core Animation (核心动画) 相对更底层. CALayer负责视图中显示内容和动画.所有动画都是作用在CALayer上的. UIView负责监听和相应事件.UIView是更高层的封装
  2. 在 iOS 中,你能看得见,摸得着的东西基本上都是UIView.比如一个按钮,一个文本标签,一个文本输入框, 一个图标等.这些都是UIView,其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时, UIView内部会自动创建一个图层 (即CALayer对象), 通过UIView的layer属性即可访问这个图层.当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView得显示.换句话说,UIView本身不具备显示的功能,是它内部的层才有显示功能.
  3. 首先 : CALayer是定义在QuartzCore框架中. CGImageRef, CGColorRef两种数据类型是定义在CoreGraphics框架中的. UIColor, UIImage是定义在UIKit框架中的. 其次 : QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用 (C语言编写) 但是UIKit只能在iOS中使用 (OC编写). 因此 : 为了保证可移植性,QuartzCore不能使用UIImage,UIColor,只能使用CGImageRef,CGColorRef.
  4. 隐式动画 (可动画属性) 什么是隐式动画 ? 当对非 Root Layer的部分属性进行修改时, 默认会自动产生一些动画效果, 而这些属性称为Animatable Properties (可动画属性). 如 : bounds : 用于设置CALayer的宽度和高度,修改这个属性会产生缩放动画. background : 用户设置CALayer的背景色, 修改这个属性会产生背景色的渐变动画. position : 用于设置CALayer的位置,修改这个属性会产生平移动画.
  5. 可以通过动画事务 (CATransaction) 关闭默认的隐式动画效果. 代码参考如下 :
      [CATransaction begin];
      [CATransaction setDisableActions:YES];
     // your code …
      [CATransaction commit];
  1. UIView和CALayer的选择. 通过CALayer就能做出跟UIView一样的界面效果.都能实现相同的显示效果,那究竟该选择谁好呢? 其实,对比CALayer,UIView多了一个事件处理的功能,也就是说,CALayer不能处理用户的触摸事件,而UIView可以.所以,如果显示出来的东西需要跟用户进行交互的话,用UIView.UIView用来接收和处理系统事件,触摸事件.如果不需要跟用户进行交互,用UIView或者CALayer都可以.当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级

二、CALayer属性

  1. 设置图层的尺寸,高度和宽度
@property CGRect bounds;
  1. 设置位置
  • 方式1:
    用来设置CALayer在父层中的位置,position相当于UIView控件的center属性
@property CGPoint position;

称为 "定位点" / "锚点", 它的取值范围是0 ~ 1, 默认值为0.5. 可以通过该属性修改position的含义

@property CGPoint anchorPoint;
  • 方式2: 直接设置frame(不建议使用)
layer.frame = CGRectMake(50, 50, 200, 200);
  1. 背景颜色(CGColorRef类型)
@property CGColorRef backgroundColor;

转换CGColor类型方法两种:

(__bridge CGColorRef _Nullable)([UIColor redColor]);
[UIColor redColor].CGColor;
  1. 设置边框颜色 ( border 边界)
redView.layer.borderColor = [UIColor whiteColor].CGColor;
  1. 设置边框宽度
redView.layer.borderWidth = 15;
  1. 设置阴影效果

阴影效果shadowColor、shadowOffset、shadowOpacity属性必须同时设置后才可以看到

  1. 设置阴影的颜色, 注意UIKit框架中的颜色不能直接设置给CGColorRef,需要.CGColor转换
 self.demoView.layer.shadowColor = [UIColor yellowColor].CGColor;
  1. 设置阴影的偏移
 self.demoView.layer.shadowOffset = CGSizeMake(5, 5);
redView.layer.shadowOffset = CGSizeZero;
  1. 设置阴影的透明度(layer的opacity相当于view的alpha)
 self.demoView.layer.shadowOpacity = 1.0;
  1. 设置阴影半径
 self.demoView.layer.shadowRadius = 10;
  1. 设置圆角效果,圆角矩形,layer剪裁
  2. 设置圆角半径
redView.layer.cornerRadius = 125;
  1. 如果控件有两层及以上就需要下面这个属性进行遮盖
redView.layer.masksToBounds = YES;

已知控件label有两层,imageView,Button,UIView默认就一层,直接设置圆角就可以裁掉,但是各控件加了图片就会变成两层,依然需要masksToBounds属性;
masksToBounds方法告诉layer将位于它之下的layer都遮盖住,这样会使圆角不被遮,但是这样会导致阴影效果没有,可以再添加一个SubLayer,添加阴影。
此处可以和UIView的clipToBounds来比较记忆(clipToBounds为yes会使其上的内容包括子视图不能超出边界)

控件截图裁剪的三种方法:

  1. 给layer设置圆角半径layer.cornerRadius
  2. view的clipToBounds 裁剪多余边缘
    设置photoView中的所有子控件如果超出了photoView的有效范围,那么超出的部分将不会显示
 photoView.clipsToBounds = YES ;

设置两边多余地方不裁剪

button.imageView.clipsToBounds = NO;
  1. 路径绘制,绘图剪裁
    矩形图片剪裁成圆并且外面设置圆环并存储

  2. 给layer设置背景图片,设置内容层(需要桥接)

redView.layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"header"].CGImage);

__bridge类型表达式的作用一般就是把 Core Foundation 中的数据类型转换成 Foundation 中的类型, 桥接的时候也会设置到一些所有权的转换等。

给UIView设置背景图片的三种方式

  1. 设置layer的contents属性
redView.layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"header"].CGImage); 
  1. 调用自定义view的drawRect: 方法进行绘制
  2. 设置view的backgroundColor,调用colorWithPatternImage来进行设置
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"me"]];
  1. 可动画属性(隐式动画)
  • 凡是文档中有 “animatable” 字样的属性都是可动画属性

  • 当对以下非 Root Layer的部分属性进行修改时, 默认会自动产生一些动画效果

  • UIView 默认情况下禁止了 layer 动画,但是在 animation block 中又重新启用了它们
    (1)bounds : 用于设置CALayer的宽度和高度,修改这个属性会产生缩放动画.
    (2)backgroundColor: 用户设置CALayer的背景色, 修改这个属性会产生背景色的渐变动画
    (3)position : 用于设置CALayer的位置,修改这个属性会产生平移动画
    (4)hidden:溶解消失动画

  • 关闭隐式动画,关闭可动画属性方法,通过动画事务 (CATransaction)

[CATransaction begin];
[CATransaction setDisableActions:YES];
      //your code …e.g.:
self.myview.layer.position = CGPointMake(10, 10);
[CATransaction commit];
  1. 3D放射形变属性(和view的transform用法一样,也有make和非make方法)
@property CATransform3D transform;

(1) 平移(当没有3D旋转的时候z值没有效果)

CATransform3D CATransform3DMakeTranslation (CGFloat tx,    CGFloat ty, CGFloat tz);
self.blueLayer.transform = CATransform3DTranslate(self.blueLayer.transform, 10, 10, 10);

(2) 缩放

CATransform3DMakeScale (CGFloat sx, CGFloat sy,    CGFloat sz);
self.blueLayer.transform = CATransform3DScale(self.blueLayer.transform, 0.8, 0.8, 0.8);

(3) 旋转
以哪个轴的哪个点进行旋转,以一个轴旋转,轴上的任何点都一样,参数填1就可以

CATransform3DMakeRotation (CGFloat angle, CGFloat x,    CGFloat y, CGFloat z);
self.blueLayer.transform = CATransform3DRotate(self.blueLayer.transform, M_PI_4 * 0.5, 1, 1, 1);

注意:上面属性如果同时使用非make方式,其中一个使用了make会导致动画只执行了make那个属性,其它属性不会再继续执行,可以通过KVC模式解决

 [self.myLayer setValue:@(rotate) forKeyPath:@"transform.rotation"];

二、方法

1、 创建自定义图层对象

+ (instancetype)layer;

2、 添加子图层

- (void)addSublayer:(CALayer *)layer;

3、将layer上的所有内容渲染到图形上下文中

CGContextRef ctx = UIGraphicsGetCurrentContext();
[redView.layer renderInContext:ctx];

4、添加动画、开始动画
一个layer中可以添加多个核心动画对象

- (void)addAnimation:(CAAnimation *)anim forKey:(NSString *)key;

5、关闭动画、停止动画、移除动画(key值与开始动画的key对应)

- (void)removeAnimationForKey:(NSString *)key;

6、layer动画移动后回到原位置的解决办法:

  • 方法一 :layer 的真实位置还在原来的位置
    // 设置layer执行完毕动画后,不要回去
   anim1.removedOnCompletion = NO; // 当核心动画执行完毕后不要从layer中移除
   anim1.fillMode = kCAFillModeForwards;
  • 方法二:layer的真实位置就是当前的位置 (该方法可以让layer和View层一起过去)
// 为animation对象设置代理
// 这里的代理没有协议, 叫做隐式代理,里面有两种方法可以选择实现
    anim1.delegate = self;
// 动画结束执行
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    self.redView.center = CGPointMake(150, 250);
}

控件有两个图层:
展示图层, 在后台移动图层中的内容

- (id)presentationLayer;

模型图层, 就是移动前原本的图层位置,移动后presentationLayer会回到该图层位置

- (id)modelLayer;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,440评论 6 30
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,083评论 5 13
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,070评论 1 23
  • 前言 本文只要描述了iOS中的Core Animation(核心动画:隐式动画、显示动画)、贝塞尔曲线、UIVie...
    GitHubPorter阅读 3,593评论 7 11
  • 转载:http://www.cnblogs.com/jingdizhiwa/p/5601240.html 1.ge...
    F麦子阅读 1,528评论 0 1