iOS动画学习-CALayer
iOS中有很多方法可以实现动画,我们可以用CAKeyframeAnimation, CABasicAnimation,CASpringAnimation(iOS9.0中添加的,实现弹簧的效果),也可以用UIView中为我们提供的动画接口,不管用哪种方法,目的就是实现动画效果,这里重点讲解CAKeyframeAnimation和CABasicAnimation。
在学习动画之前,我们需要了解一些知识,大家都知道动画是作用在图层上面的,我们首先要了解图层。
认识CALayer
大家平时使用最多的就是UIView,我们创建一个视图时,其实就是创建了一个与视图相关的图层,视图负责管理着创建的图层,通过图层来显示相应内容。我们可以直接创建一个图层,然后将它添加到父图层上,这样就能看到我们创建的图层(代码如下)
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(50, 200, 80, 80);
layer.backgroundColor = [UIColor greenColor].CGColor;
[self.view.layer addSublayer:layer];
效果图:

可能大家想知道 CALayer和UIView的区别在哪?也许最大的区别就是UIView可以和用户交互,CALayer不能交互。相信我们的目的并不是显示一个纯色的矩形块,其实CALayer也可以显示其他类型的内容。
CALayer属性
contents
查看头文件可以知道这个属性的类型为id,也就是说他可以显示任何类型的对象,但实践中,如果不是CGImage类型,将会显示空白,这点会让人产生疑惑,其实还有更奇怪的,你要赋给的类型不是CGImage,而是CGImageRef(指向CGImage结构的指针),UIImage有一个CGImage属性,返回CGImageRef,但是如果把这个值直接赋给contents的话会得到编译错误,因为CGImageRef是一个Core Foundation类型,我们需要用如下代码进行赋值:
layer.contents = (__bridge id)image.CGImage;
以上代码块的前提是使用ARC,不使用ARC的话,不需要__bridge
接下来我们来显示一张图片,代码如下:
// 图片是一个200x200的图,layer的frame故意设置成矩形,为了演示变形
UIImage *image = [UIImage imageNamed:@"image.png"];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(50, 150, 80, 100);
layer.contents = (__bridge id)image.CGImage;
[self.view.layer addSublayer:layer];
效果图如下:

contentGravity
如上面代码所示,我们得到了一个变形了的图片,这当然不是我们想要的,如果想让图片正确显示,我们可以设置contentGravity,这个属性用法类似UIView中的contentMode属性,我们可以看一下它的枚举:
- kCAGravityCenter
- kCAGravityTop
- kCAGravityBottom
- kCAGravityLeft
- kCAGravityRight
- kCAGravityTopLeft
- kCAGravityTopRight
- kCAGravityBottomLeft
- kCAGravityBottomRight
- kCAGravityResize
- kCAGravityResizeAspect
- kCAGravityResizeAspectFill
是不是看着很熟悉啊!这对上面图片变形,我们可以设置这个属性值为kCAGravityResizeAspect,这样就能得到我们想要的正确的效果了
添加代码:
layer.contentsGravity = kCAGravityResizeAspect;
就能得到显示正确的图:

contentsScale
contentsScale属性定义了寄宿图的像素尺寸和视图大小的比例,默认情况下它是一个值为1.0的浮点数。
如果你设置了contentsGravity属性,contentsScale就不在寄宿图有影响,因为它已经被拉伸以适应图层的边界。
contentsScale属性其实属于支持高分辨率(又称Hi-DPI或Retina)屏幕机制的一部分,它用来判断在绘制图层的时候应该为寄宿图创建的空间大小,和需要显示的图片的拉伸度(假设并没有设置contentsGravity属性),UIView有一个类似功能但是非常少用到的contentScaleFactor属性。
maskToBounds
如果把contentsGravity设置成kCAGravityCenter,我们看到图片超出了视图边界

UIView有一个叫做clipsToBounds的属性可以用来决定是否显示超出边界的内容,CALayer对应的属性叫做masksToBounds,把它设置为YES,即可看到图片被剪切了,如下图:

custom drawing
给contents赋CGImage的值不是唯一的设置寄宿图的方法。我们也可以直接用Core Graphics直接绘制寄宿图。能够通过继承UIView并实现-drawRect:方法来自定义绘制。
如果你不需要寄宿图,那就不要创建这个方法了,这会造成CPU资源和内存的浪费,这也是为什么苹果建议:如果没有自定义绘制的任务就不要在子类中写一个空的-drawRect:方法。
当视图出现在屏幕上时,-drawRect:方法会被调用,通常是开发者自己调用-setNeedsDisplay方法
CALayer有一个可选的delegate属性,实现了CALayerDelegate协议,当CALayer需要一个内容特定的信息时,就会从协议中请求。
当需要被重绘时,CALayer会请求它的代理给它一个寄宿图来显示。它通过调用下面这个方法做到的:
- (void)displayLayer:(CALayer *)layer
如果代理想直接设置contents属性的话,它就可以在这个方法中做,不然没有别的方法可以调用了
如果代理不实现-displayLayer:方法,CALayer就会转而尝试调用下面这个方法:
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
在调用这个方法之前,CALayer创建了一个合适尺寸的空寄宿图(尺寸由bounds和contentsScale决定)和一个Core Graphics的绘制上下文环境,为绘制寄宿图做准备,它作为ctx参数传入。
如下例子:
代码:
- (void)viewDidLoad {
[super viewDidLoad];
CALayer *blueLayer = [CALayer layer];
blueLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
blueLayer.backgroundColor = [UIColor blueColor].CGColor;
blueLayer.delegate = self;
blueLayer.contentsScale = [UIScreen mainScreen].scale; //add layer to our view
[self.view.layer addSublayer:blueLayer];
[blueLayer display];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextSetLineWidth(ctx, 5);
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextStrokeEllipseInRect(ctx, layer.bounds);
}
效果图:

iOS动画学习-CALayer的更多相关文章
- iOS动画学习-视觉效果
CALayer不仅仅是iOS动画学习-CALayer中介绍的那些内容,他还有一些其他属性,比如shadowColor,borderWidth,borderColor等等,这些属性我们只需要简单点设置就 ...
- iOS动画学习
学习一下动画,感谢以下大神的文章: UIView:基础动画.关键帧动画.转场动画 Core Animation :基础动画,关键帧动画,动画组,转场动画,逐帧动画 CALayer :CALaye ...
- iOS 动画学习
图层树.寄宿图以及图层几何学(一)图层的树状结构 技术交流新QQ群:414971585 巨妖有图层,洋葱也有图层,你有吗?我们都有图层 -- 史莱克 Core Animation其实是一个令人误解的命 ...
- ios 动画学习的套路 (二)
有它们俩你就够了! 说明:下面有些概念我说的不怎么详细,网上实在是太多了,说了我觉得也意义不大了!但链接都给大家了,可以自己去看,重点梳理学习写动画的一个过程和一些好的博客! (一) 说说这两个三方库 ...
- iOS动画学习 -隐式动画
事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.你并不需要在Core Animation中手动打开动画,但是你需要明确地关闭它,否则它会一直存在. 当你改变 ...
- iOS 动画学习之视图控制器转场动画
一.概述 1.系统会创建一个转场相关的上下文对象,传递到动画执行器的animateTransition:和transitionDuration:方法,同样,也会传递到交互Controller的star ...
- iOS 动画笔记 (一)
你也肯定喜欢炫酷的动画! 在APP中,动画就是一个点睛之笔!可以给用户增加一些独特的体验感,估计也有许多的和我一样的,看着那些觉得不错的动画,也就只能流口水的孩子,毕竟可能不知道从哪里下手去写!动画学 ...
- iOS 动画Animation - 5:UIBezier
首先说明:这是一系列文章,參考本专题下其它的文章有助于你对本文的理解. 在之前的bolg中大家会发现总是会出现UIBezier,可是我也没有做过多介绍,今天就集中介绍一下UIBezier.首先.UIB ...
- iOS核心动画学习整理
最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...
随机推荐
- Calendar使用
1简单例子 package com.kungeek.tip; import java.text.SimpleDateFormat; import java.util.Calendar; import ...
- 什么是ZigBee、Wifi无线技术?有什么优势?
Zigbee:是基于IEEE802.15.4标准的低功耗个域网协议.根据这个协议规定的技术是一种短距离.低功耗的无线通信技术.这一名称来源于蜜蜂的八字舞,由于蜜蜂(bee)是靠飞翔和"嗡嗡& ...
- File 常用方法
1.判断当前文件是否封装的文件夹目录 //返回true--是,false--不是 File file =new File("C:\\Users\\mac\\Desktop\\复习.txt&q ...
- 微信小程序 生命周期函数详解
微信小程序 生命周期函数 小程序中 判断当前首页是从其他页面返回,还是由入口打开 由于小程序的数据在我们退出小程序时并没有得到释放,因此再次点击开来数据依然没有变成初始化 解决方法:在小程序 data ...
- 【PHP】最详细PHP从入门到精通(二)——PHP中的函数
PHP从入门到精通 之PHP中的函数 各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持.PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新 ...
- poj2976(01分数规划)
poj2976 题意 给出 a b 数组,一共 n 对数,其中最多可以去掉 k 对,问怎样使剩下比率(原始比率是 $ \frac{\sum_{i=1}^{n} a}{\sum_{i=1}^{n} b} ...
- FLAnimatedImageView处理gif过程
FLAnimatedImageView处理gif过程 时间控制原理 GIF图片每一帧的delayTime可能都不一样: 在展示下一帧的时间控制机制,不能根据以第一帧为准: 或总动画时长除以帧数来简单做 ...
- 给Linux系统/网络管理员准备的Nmap命令的29个实用范例
我将用两个不同的部分来涵盖大部分NMAP的使用方法,这是nmap关键的第一部分.在下面的设置中,我使用两台已关闭防火墙的服务器来测试Nmap命令的工作情况. 192.168.0.100 – serve ...
- 测序分析软件-trimmomatic的记录
1.下载相关软件,网址:http://www.usadellab.org/cms/index.php?page=trimmomatic,它有源代码和二进制两种文件(建议都下载,然后合并成一个文件,因为 ...
- 关于Myeclipse不能加载已有项目的问题
如果缺少.project文件,你可以新建一个同名项目,把Use default location 去掉,选择要加载的项目,完成