iOS 高级核心动画 day01 - 图层树、UIView、CA
2021-07-08 本文已影响0人
望穿秋水小作坊
一、图层树(认识 UIView 和 CALayer)
1. iOS 中所有的视图都从哪个视图派生而来?
- iOS 中,所有的视图都从一个叫做
UIView
的基类派生而来
2. UIView
可以做些什么事情(至少说三点)?
-
UIView
可以处理触摸事件。 -
UIView
可以基于 Core Graphics 绘图。 -
UIView
可以做简单动画,类似滑动、渐变、旋转、缩放。
3. CALayer 和 UIView 的异同点(至少各说一个)?
- 同:CALayer 和 UIView 都是被层级关系树管理的矩形框,同样也可以包含一些内容(像图片、文本或背景色)
- 异:CALayer 和 UIView 最大的不同是
不处理用户的交互
4. 为什么不用一个简单层级来处理所有事情,而且提供 UIView 和 CALayer 呢?
- 主要为了职责分离,这样也能避免很多重复代码。
- 比如在 iOS 平台,由 UIView 处理用户手
指触摸事件
,在 Mac OS 平台由 NSView 处理用户鼠标键盘事件
,但是可以共用 CALayer。 - 这也就是为什么iOS有UIKit和UIView,但是Mac OS有AppKit和NSView的原因
二、寄宿图(layer.contents)
1. layer.contents 是干啥的?如何用单纯的一个 UIView
展示一张图片?
- CALayer 有个一个属性叫做
contents
,这个属性使用来展示 CGImage 的。 -
layer.contents
也就是寄宿图 - 使用 UIView 的 layer 展示
image.CGImage
方法如下:
UIImage *snowImage = [UIImage imageNamed:@"snow.png"];
self.layerView.layer.contents = (__bridge id _Nullable)(snowImage.CGImage);
2. 给 contents 赋值 CGImage 的值是唯一设置寄宿图的方法吗?
- 不是唯一方法。
- 还可以通过继承 UIView 并且实现
-drawRect:
方法来自定义绘制。
3. 为什么如果不需要寄宿图,就不要创建 -drwaRect
方法?
- 因为对于 UIView 来说,寄宿图并不是必须的,它并不在意那到底是单调的颜色还是有一个图片的实例。
- 如果 UIView 检测到
-drawRect:
方法被调用了,系统就会为视图分配一个寄宿图,这个寄宿图的像素尺寸等于视图大小乘以 contentsScale 的值。 - 如果你不需要寄宿图,那就不要创建这个方法了,这会造成CPU资源和内存的浪费,这也是为什么苹果建议:如果没有自定义绘制的任务就不要在子类中写一个空的-drawRect:方法。
4. layer.contentsScale 是干啥的?
- contentsScale属性定义了寄宿图的像素尺寸和视图大小的比例,默认情况下它是一个值为1.0的浮点数。
- 如果contentsScale设置为1.0,将会以每个点1个像素绘制图片,如果设置为2.0,则会以每个点2个像素绘制图片,这就是我们熟知的Retina屏幕。
5. iOS视图绘制有哪三种坐标系统?
-
点
-- 在 iOS 和 MacOS 中最常见的坐标系
。点就像是虚拟的像素,也被称为逻辑像素。在标准设备上,一个点就是一个像素,但是在 Retina 设备上,一个点等于 2*2 个像素。iOS 用点作为屏幕的坐标测算体系就是为了在 Retina 设备和普通设备上能有一致的视觉效果
。 -
像素
-- 物理像素坐标并不会用来屏幕布局,但是仍然与图片有相对关系。UIImage 是一个屏幕分辨率解决方案,所以指定点来度量大小。但是一些底层图片表示如 CGImage 就会使用像素,所以你要清除在 Retina 设备和普通设备上,他们表现出来不同的大小。 -
单位
-- 对于与图片大小或是图层边界相关的显示,单位坐标是一个方便的度量方式,当大小改变的时候,也不需要再次调整。单位坐标在 OpenGL 这种纹理坐标系中用得很多,Core Animation 中也用到了单位坐标。
6. layer.contentsRect 是哪种坐标系?
- 默认的 contentsRect 是 {0,0,1,1},是单位坐标系。这意味着整个寄宿图默认都是可见的,如果我们制定一个小一点的矩形,图片就会被裁剪,如下图
7. layer.contentsRect 可以实现雪碧图image sprites(图片拼合)的效果吗?
- 可以。
8. layer.contentsCenter 有什么作用?
- 看名字你可能以为它可能跟图片的位置有关,不过这个名字着实误导了你。
- contentsCenter 其实是一个 CGRect,它定义了一个固定的边框和一个在图层上可拉伸的区域。
- 他工作起来的效果和UIImage里的-resizableImageWithCapInsets: 方法效果非常类似