转载自:http://www.cofcool.net/development/2015/06/19/ios-study-note-eight-CALayer-info/

The CALayer class manages image-based content and allows you to perform animations on that content. Layers are often used to provide the backing store for views but can also be used without a view to display content. A layer’s main job is to manage the visual content that you provide but the layer itself has visual attributes that can be set, such as a background color, border, and shadow.

从上述文档中,可以看到CALayer主要负责显示内容,通过UIView的layer属性来调整UIView的显示效果,包括背景颜色、边框、阴影等和控制内容的动画效果等。CALayer是被定义在QuartzCore框架中的,因此要想使用CALayer,先导入QuartzCore框架。

常用属性:

// 宽度和高度
@property CGRect bounds; // 位置(默认指中点,具体由anchorPoint决定)
@property CGPoint position; // 锚点(x,y的范围都是0-1),决定了position的含义
@property CGPoint anchorPoint; // 背景颜色(CGColorRef类型)
@property CGColorRef backgroundColor; // 形变属性
@property CATransform3D transform; // 边框颜色(CGColorRef类型)
@property CGColorRef borderColor; // 边框宽度
@property CGFloat borderWidth; // 圆角半径
@property CGColorRef borderColor; // 内容(比如设置为图片CGImageRef)
@property(retain) id contents;

UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层。当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。换句话说,UIView本身不具备显示的功能,是它内部的图层才有显示功能。通过操作CALayer对象可以方便的调整UIView的一些外观属性。需要注意的是CALayer不能处理用户的触摸事件,而UIView可以。CALayer有2个非常重要的属性:position和anchorPoint。

  • @property CGPoint position:该属性用来设置CALayer在父层中的位置,以父层的左上角为原点(0, 0)

  • @property CGPoint anchorPoint:该属性称为“定位点”、“锚点”,决定着CALayer身上的哪个点会在position属性所指的位置,以自己的左上角为原点(0, 0),它的x、y取值范围都是0~1,默认值为(0.5, 0.5)

每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)。所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画(当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果,而这些属性称为Animatable Properties(可动画属性))。常见的Animatable Properties:

bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画。
backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画。
position:用于设置CALayer的位置。修改这个属性会产生平移动画。

可以通过动画事务(CATransaction)关闭默认的隐式动画效果。

[CATransaction begin];
[CATransaction setDisableActions:YES];
self.myview.layer.position = CGPointMake(10, 10);
[CATransaction commit];

自定义图层方法:

1. 方法1

  1. 创建一个CALayer的子类,然后覆盖drawInContext:方法,使用Quartz2D API进行绘图。
  2. 在.m文件中覆盖drawInContext:方法,在里面绘图。

     // 绘制一个实心三角形
    - (void)drawInContext:(CGContextRef)ctx {
    // 设置为蓝色
    CGContextSetRGBFillColor(ctx, 0, 0, 1, 1); // 设置起点
    CGContextMoveToPoint(ctx, 50, 0);
    // 从(50, 0)连线到(0, 100)
    CGContextAddLineToPoint(ctx, 0, 100);
    // 从(0, 100)连线到(100, 100)
    CGContextAddLineToPoint(ctx, 100, 100);
    // 合并路径,连接起点和终点
    CGContextClosePath(ctx); // 绘制路径
    CGContextFillPath(ctx);
    }
  3. 在控制器中添加图层到屏幕上,一定要调用setNeedsDisplay方法,这样才会触发drawInContext:方法,从而进行绘图。

     MYLayer *layer = [MYLayer layer];
    // 设置层的宽高
    layer.bounds = CGRectMake(0, 0, 100, 100);
    // 设置层的位置
    layer.position = CGPointMake(100, 100);
    // 开始绘制图层
    [layer setNeedsDisplay];
    [self.view.layer addSublayer:layer];

2. 方法2

设置CALayer的delegate,然后让delegate实现drawLayer:inContext:方法,当CALayer需要绘图时,会调用delegate的drawLayer:inContext:方法进行绘图。需要注意的是:不能再将某个UIView设置为CALayer的delegate,因为UIView对象已经是它内部根层的delegate,再次设置为其他层的delegate就会出问题。

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

     CALayer *layer = [CALayer layer];
    // 设置delegate
    layer.delegate = self;
    // 设置层的宽高
    layer.bounds = CGRectMake(0, 0, 100, 100);
    // 设置层的位置
    layer.position = CGPointMake(100, 100);
    // 开始绘制图层
    [layer setNeedsDisplay];
    [self.view.layer addSublayer:layer];
  2. 让CALayer的delegate(前面设置的控制器)实现drawLayer:inContext:方法。

     // 画一个矩形框
    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    // 设置蓝色
    CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1); // 设置边框宽度
    CGContextSetLineWidth(ctx, 10); // 添加一个跟层一样大的矩形到路径中
    CGContextAddRect(ctx, layer.bounds); // 绘制路径
    CGContextStrokePath(ctx);
    }

3. 总结

当UIView需要显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法,从而完成绘制。平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由图层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入图层的CGContextRef中,然后被拷贝至屏幕显示出来。

CALayer 进阶的更多相关文章

  1. iOS开发——UI进阶篇(十七)CALayer,核心动画基本使用

    一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以 ...

  2. [iOS UI进阶 - 6.0] CALayer

    A.基本知识 1.需要掌握的 CALayer的基本属性 CALayer和UIView的关系 position和anchorPoint的作用   2.概念 在iOS中,你能看得见摸得着的东西基本上都是U ...

  3. iOS UI进阶-2.0 CALayer

    在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图 ...

  4. iOS进阶读物

    不知不觉作为 iOS 开发也有两年多的时间了,记得当初看到 OC 的语法时,愣是被吓了回去,隔了好久才重新耐下心去啃一啃.啃了一阵,觉得大概有了点概念,看到 Cocoa 那么多的 Class,又懵了, ...

  5. 浅谈iOS程序员的成长和进阶

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  6. nodejs进阶(6)—连接MySQL数据库

    1. 建库连库 连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 mysql> CREATE DATABA ...

  7. nodejs进阶(4)—读取图片到页面

    我们先实现从指定路径读取图片然后输出到页面的功能. 先准备一张图片imgs/dog.jpg. file.js里面继续添加readImg方法,在这里注意读写的时候都需要声明'binary'.(file. ...

  8. JavaScript进阶之路(一)初学者的开始

    一:写在前面的问题和话 一个javascript初学者的进阶之路! 背景:3年后端(ASP.NET)工作经验,javascript水平一般般,前端水平一般般.学习资料:犀牛书. 如有误导,或者错误的地 ...

  9. nodejs进阶(3)—路由处理

    1. url.parse(url)解析 该方法将一个URL字符串转换成对象并返回. url.parse(urlStr, [parseQueryString], [slashesDenoteHost]) ...

随机推荐

  1. 第一次使用unity3d

    今天暂且做个记录,因为第一使用了unity3d,进行了很长时间的安装和调试,进行了简单的使用,能简单的在页面上面建立了一个方块和一个球. 简单了解了unity中的一些基本概念.总结一下,一个物体可以有 ...

  2. js 时间

    <html> <head> <meta charset="utf-8" /> <title></title> <s ...

  3. sqlserver-根据2张表的id更新其他列值

    update a set a.ORGID = (select b.ORG_ID from PT_SERVICE b where a.SERVICEOID = b.SERVICEOID and a.OR ...

  4. 关于tab选项卡,选项的css问题。

    刚开始的思路是:让上面的选中的选项背景变成白色,让下面的层position:absolute;z-index:-1;top:1px,就能盖得上上面的横线.实践证明,这样是能盖得上,但是单选按钮不能点了 ...

  5. 使用btoa和atob来进行Base64转码和解码

      btoa: 将普通字符串转为Base64字符串 atob: 将Base64字符串转为普通字符串   说明:window.btoa不支持汉字:   ===>使用window.encodeURI ...

  6. layer弹出层

    最近因为项目要求做了一个layer弹出层demo,先看效果图 好了,现在开始上代码 index.jsp <%@ page language="java" import=&qu ...

  7. Android OpenGL ES(五)GLSurfaceView .

    Android OpenGL ES 相关的包主要定义在 javax.microedition.khronos.opengles    GL 绘图指令 javax.microedition.khrono ...

  8. SEO策略与细节:细节决定成败

    昨天展开seo探讨会.听了一场医疗界seo大神的讲座.收益匪浅今天讲他的演讲内容整理出来与大家分享.希望对医疗界的seo带来些帮助.站长们一起成长! 一.首页 1.元标签设置 标题:上海癫痫病医院哪家 ...

  9. runtime基础

    前言 学习Objective-C的运行时Runtime系统是很有必要的.个人觉得,得之可得天下,失之则失天下. Objective-C提供了编译运行时,只要有可能,它都可以动态地运作.这意味着不仅需要 ...

  10. iOS项目架构 小谈

    层级结构,自底向上 持久层(File,Realm,SQLite)<==>网络层(相信每个公司都有自己的网络层吧)==>业务层(ViewModel)==>展示层(View,VC) ...