CALayer 详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CALayer 详解相关的知识,希望对你有一定的参考价值。
参考技术A ios 视图在层级关系中相互嵌套,一个视图可以管理它的所有子视图的位置。
CALayer类在概念上和UIView类似,同样也是一些被层级关系树管理的矩形块,同样也可以包含一些内容(像图片,文本或者背景色),管理子图层的位置。它们有一些方法和属性用来做动画和变换。和UIView最大的不同是CALayer不处理用户的交互。CALayer并不清楚具体的 响应链 (iOS通过视图层级关系用来传送触摸事件的机制),于是它并不能够响应事件。
每个UIVIew都有一个CALayer实例的图层属性,视图的职责就是创建并管理这个图层,以确保当子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作。
虽然苹果已经通过UIView的高级API进行动画的管理并且使得动画变得简单易用。CALayer功能更为灵活:
CALayer 有一个属性叫做contents,这个属性的类型被定义为id。如果你给contents赋的不是CGImage,那么你得到的图层将是空白的。
contents这个奇怪的表现是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。如果你试图在iOS平台上将UIImage的值赋给它,只能得到一个空白的图层。一些初识Core Animation的iOS开发者可能会对这个感到困惑。
你真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针。UIImage有一个CGImage属性,它返回一个"CGImageRef",如果你想把这个值直接赋值给CALayer的contents
,那你将会得到一个编译错误。因为CGImageRef并不是一个真正的Cocoa对象,而是一个Core Foundation类型。
尽管Core Foundation类型跟Cocoa对象在运行时貌似很像(被称作toll-free bridging),他们并不是类型兼容的,不过你可以通过bridged关键字转换。如果要给图层的寄宿图赋值,你可以按照以下这个方法:
contentsGravity与UIView中的contentsMode类似,UIVIewImage中可以通过设置contentMode 属性,使得添加的图片更适合。
UIView大多数视觉相关的属性比如contentMode
,对这些属性的操作其实是对对应图层的操作。
CALayer与contentMode对应的属性叫做contentsGravity,但是它是一个NSString类型,而不是像对应的UIKit部分,那里面的值是枚举。contentsGravity可选的常量值有以下一些:
contentsScale属性定义了寄宿图的像素尺寸和视图大小的比例,默认情况下它是一个值为1.0的浮点数。
如果你只是单纯地想放大图层的contents
图片,你可以通过使用图层的transform
和affineTransform属性来达到这个目的。
contentsScale属性其实属于支持高分辨率(又称Hi-DPI或Retina)屏幕机制的一部分。它用来判断在绘制图层的时候应该为寄宿图创建的空间大小,和需要显示的图片的拉伸度(假设并没有设置contentsGravity属性)。
如果contentsScale 设置为1.0,将会以每个点1个像素绘制图片,如果设置为2.0,则会以每个点2个像素绘制图片,这就是我们熟知的Retina屏幕。
这并不会对我们在使用kCAGravityResizeAspect时产生任何影响,因为它就是拉伸图片以适应图层而已,根本不会考虑到分辨率问题。但是如果我们把contentsGravity设置为kCAGravityCenter(这个值并不会拉伸图片),那将会有很明显的变化
注意:
当我们对Layer添加图片时设置contentsGravity为kCAGravityResizeAspect,此时设置contentsScale不会对图片显示有任何影响。但是当我们把contentsGravity设置成kCAGravityCenter,这时就需要通过手动设置contentsScale修复图片不正常显示问题;
和UIImage不同,CGImage没有拉伸的概念。当我们使用UIImage类去读取我们的雪人图片的时候,他读取了高质量的Retina版本的图片。但是当我们用CGImage来设置我们的图层的内容时,拉伸这个因素在转换的时候就丢失了。不过我们可以通过手动设置contentsScale来修复这个问题。
当我们在Layer中添加图片,但图片超出Layer范围时,会有显示不全的问题。但不管是UIView还是Layer都可以对超出范围的内容或子视图进行绘制。
UIView中用的是clipsToBounds 来确定是否显示超出的内容是否显示,CALayer中的则是 masksToBounds ,当把其设置为YES时,即显示界外内容。
ios开发讲解之anchorPoint和position详解
相信初接触到CALayer的人都会遇到以下几个问题: 为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与position有什么关系?
每一个UIView都默认关联着一个CALayer, UIView有frame、bounds和center三个属性,CALayer也有类似的属性,分别为frame、bounds、position、anchorPoint。那position、anchorPoint是什么呢?先看看两者的原型,可知都是CGPoint点。
@property CGPoint position ;
@property CGPoint anchorPoint ;
以上是关于CALayer 详解的主要内容,如果未能解决你的问题,请参考以下文章
ios开发讲解之anchorPoint和position详解
如果 CALayer 边界如何独立地 CALayer 图像缩放