UIView, CALayer

简介

在iOS中使用UIWindow和UIView在屏幕上显示APP的内容。UIWindow为APP提供了一个底层的容器,用来展示内容,其本身不会显示出来。而UIView可以在UIWindow这个容器里显示出某一部分的内容,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。你可以创建不同的View去显示图片、文字,或者其他组合在一起的视图,你可以使用View去管理、组织其他的View。

在一个应用中,至少要有一个Window,一个View,来去显示应用的内容。在UIKit和其他的一些系统库中,提供了一些定义好的View供你使用,button、label、tableView等等。如果这些不能满足你的需求,也可以自己绘制View、自行获取触控事件。

UIView与CALayer

在iOS中,所有的 view 都是由一个底层的 layer 来驱动的。view 和它的 layer 之间有着紧密的联系,view 其实直接从 layer 对象中获取了绝大多数它所需要的数据。

  1. 每个UIView都有一个层CALayer,控制着各自在屏幕上显示的内容。
    UIView真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性,例如frame,bounds等,实际上内部都是在访问它所包含的CALayer的相关属性。对比CALayer,UIView多了一个事件处理的功能。CALayer不能处理用户的触摸事件,而UIView可以


  1. UIView内部默认有个CALayer对象(层),通过layer属性可以访问这个层。要注意的是,这个默认的层不允许重新创建,但可以往层里面添加子层
  • UIView可以通过addSubview:方法添加子视图,类似地,CALayer可以通过addSublayer:方法添加子层
  • UIView可以通过subviews属性访问所有的子视图,类似地,CALayer也可以通过sublayers属性访问所有的子层
  • UIView可以通过superview属性访问父视图,类似地,CALayer也可以通过superlayer属性访问父层


  1. 可以通过CALayer修改UIView的界面属性。例如设置圆角、阴影、边框、旋转等等。
  • 阴影
    view.layer.shadowOffset = CGSizeMake(10, 10);
    view.layer.shadowColor = [[UIColor cyanColor] CGColor];
    view.layer.shadowOpacity = 0.3;
  • 旋转
    //角度M_PI_4,(x, y, z)维度
    view.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);


  1. UIView是定义在UIKit框架中的。CALayer是定义在QuartzCore框架中的。CGImage、CGColor是定义在CoreGraphics框架中的。QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和macOS上都能使用,但是UIKit只能在iOS中使用。为了保证可移植性,QuartzCore不能使用UIColor,只能使用CGColor。


  1. CALayer的 position、anchorPoint、frame、bounds 属性
  • position和anchorPoint属性都是CGPoint类型的

  • position 是 layer 相对 superLayer 坐标空间的位置,可以用来设置CALayer 在 superLayer 中的位置,它是以父层的左上角为坐标原点(0, 0)

  • anchorPoint称为"定位点",它决定着 CALayer 身上的哪个点会在position 属性所指的位置。它的 x、y 取值范围都是0~1。



    anchorPoint 默认值为(0.5, 0.5),在这种情况下,CALayer 的中心点会在 position 所指定的位置上,如下图所示:


  • 当初始化UIView时,只设置View的bounds,这种情况下视图的位置如下图:



    设置view的frame、bounds时候,实际上就是在设置view里对应layer的frame、bounds属性。
    上面的情况设置 layer 的 bounds 为 (0, 0,80,80),由于没有设置 layer 的 frame 值,系统会根据 layer 的 bounds、anchorPoint、position 的属性值来计算获得 frame 值,anchorPoint默认为(0.5, 0.5) ,position默认值为(0, 0)

frame.origin.x = position.x - anchorPoint.x * bounds.size.width;  
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;

所以获取到 frame 值为 (-40, -40, 80, 80),所以就呈现出图中视图的位置,x y 值为负,有一部分已经超出屏幕。
根据上面的计算方法可知,当改变 position、anchorPoint 会改变 frame 的值,改变视图的位置。
position 与 anchorPoint 的改变值互不影响。

The frame rectangle is position and size of the layer specified in the superlayer’s coordinate space. For layers, the frame rectangle is a computed property that is derived from the values in thebounds, anchorPoint and position properties. When you assign a new value to this property, the layer changes its position and bounds properties to match the rectangle you specified. The values of each coordinate in the rectangle are measured in points.


  1. 当对手动创建的 layer的部分属性进行相应的修改时,默认会自动产生一些动画效果。例如修改layer的bounds、backgroundColor、position是,会产生动画效果,如下图上面是创建的CALayer,下面是创建的UIView,分别改变其位置和高度,对手动创建的 layer会有动画效果:



  1. UIView的详细显示过程
  • 当UIView需要显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法

  • 平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入层的CGContextRef中,然后被拷贝至屏幕



CALayer

1、CALayer 的 mask 属性
/* A layer whose alpha channel is used as a mask to select between the
 * layer's background and the result of compositing the layer's
 * contents with its filtered background. Defaults to nil. When used as
 * a mask the layer's `compositingFilter' and `backgroundFilters'
 * properties are ignored. When setting the mask to a new layer, the
 * new layer must have a nil superlayer, otherwise the behavior is
 * undefined. Nested masks (mask layers with their own masks) are
 * unsupported. */

@property(nullable, strong) CALayer *mask;

当设置某个 layer 的 mask 属性之后,只会显示 layer 和 mask 两者重叠的部分,其余部分不会显示,呈现透明。
如下面例子所示,为了方便观察,设置了两个 View 叠在一起,在view2 的 layer 上设置 mask 遮盖,遮盖为椭圆形,设置了之后只显示 view2 和 mask 的重叠部分,即椭圆部分,其余部分没有显示,而且是透明的,显示出了最底层的 view1。

我们可以利用 layer 的 mask 属性做些什么呢?
可以设置渐变色的字体,如下图所示:



同样的可以设置渐变色的图片、剪切图片等。
也可以用来实现如 Twitter 的开屏动画效果:


2、 CALayer addAnimation

当你给一个 CALayer 添加动画的时候,动画其 实并没有改变这个 layer 的实际属性。取而代之的,系统会创建一个原始 layer 的拷贝。在文档中,苹果称这个原始 layer 为 Model Layer ,而这个复制的 layer 则被称为 Presentation Layer 。 Presentation Layer 的属性会随着动画的进度实时改变,而 Model Layer 中对应的属性则并不会改变。所以如果你想要获取动画中每个时刻的状态,请使用 layer 的 func presentationLayer 。

/* Returns a copy of the layer containing all properties as they were
 * at the start of the current transaction, with any active animations
 * applied. This gives a close approximation to the version of the layer
 * that is currently displayed. Returns nil if the layer has not yet
 * been committed.
 *
 * The effect of attempting to modify the returned layer in any way is
 * undefined.
 *
 * The `sublayers', `mask' and `superlayer' properties of the returned
 * layer return the presentation versions of these properties. This
 * carries through to read-only layer methods. E.g., calling -hitTest:
 * on the result of the -presentationLayer will query the presentation
 * values of the layer tree. */

- (nullable instancetype)presentationLayer;

/* When called on the result of the -presentationLayer method, returns
 * the underlying layer with the current model values. When called on a
 * non-presentation layer, returns the receiver. The result of calling
 * this method after the transaction that produced the presentation
 * layer has completed is undefined. */

- (instancetype)modelLayer;


Reference

View Programming Guide for iOS
http://www.cnblogs.com/mjios/archive/2013/04/14/3020975.html
http://blog.csdn.net/weiwangchao_/article/details/7771538

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

推荐阅读更多精彩内容