XZ_iOS之核心动画高级技巧之给UIView设置图片
在 UIView 上直接设置图片的话,需要通过 layer 层进行操作。
UIView
UIView 是视图,即屏幕上显示的矩形块,比如图片、文字或视频。它能够拦截类似于鼠标点击或者触摸手势等用户输入。视图在层级关系中可以相互嵌套,一个视图可以管理它的所有子视图的位置。
UIView 可以处理触摸事件,支持基于 Core Graphics 绘图,可以做放射变换(例如旋转或者缩放),或者简单的类似于滑动或者渐变的动画。
CALayer
CALayer是图层,概念上与 UIView 类似,也是被层级关系管理的矩形块,同样可以包含一些内容(像图片、文本和背景色),管理子图层的位置。也有一些方法和属性用来做动画和变换。
和 UIView 最大的不同是 CALayer 不处理用户的交互。因为 CALayer 并不清楚具体的响应链(iOS通过视图层级关系用来传送触摸事件的机制),于是它并不能够响应事件,即使它提供了一些方法来判断是否一个触点在图层的范围之内。
平行的层级关系
每一个 UIView 都有一个 CALayer 实例的图层属性,也就是所谓的 backing layer,视图的职责就是创建并管理这个图层,以确保当子图层在层级关系中添加或被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作。
实际上,这些背后关联的图层才是真正用来在屏幕上显示和做动画,UIView 仅仅是对它的一个封装,提供了一些 iOS 类似于处理触摸的具体功能,以及 Core Animation 底层方法的高级接口。
为什么iOS要基于UIView和CALayer提供两个平行的层级关系呢?原因在于要职责分离,这样也能避免很多重复代码。在 iOS 和 Mac OS 两个平台上,事件和用户交互有很多地方的不同,基于多点触控的用户界面和基于鼠标键盘有着本质的区别,这就是为什么 iOS 有 UIKit 和 UIView,但是 Mac OS 有 AppKit 和 NSView 的原因。他们功能上很相似,但是在实现上有着显著的区别。
图层的能力
UIView没有暴露出来的CALayer的功能:
- 阴影,圆角,带颜色的边框
- 3D变换
- 非矩形范围
- 透明遮罩
- 多级非线性动画
使用图层
使用图层关联的视图而不是 CALayer 的好处在于,你能在使用所有 CALayer 底层特性的同时,也可以使用 UIView 的高级 API(比如自动排版,布局和事件处理)。
当满足以下条件时,你可能更需要使用 CALayer 而不是 UIView:
- 开发同时可以在 Mac OS 上运行的跨平台应用
- 使用多种 CALayer 的子类,并且不想创建额外的 UIView 去包装它们所有
- 做一些对性能特别挑剔的工作,比如,对 UIView 一些可忽略不计的操作都会引起显著的不同
当然,这些例子很少见,总的来说,处理视图会比单独处理图层更加方便。
CALayer寄宿图
即图层中包含的图。下面的思维导图是 CALayer 的属性:
contents属性
给 UIView 设置图片,即给 CALayer 的 contents 属性设置值,代码如下:
UIView *layerView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];
[self.view addSubview:layerView];
layerView.backgroundColor = [UIColor whiteColor];
UIImage *image = [UIImage imageNamed:@"宠物网_狗和鸭子.jpg"];
layerView.layer.contents = (__bridge id)image.CGImage;
layerView.layer.contentsGravity = kCAGravityResizeAspect;
contentsRect属性
使用 CALayer 的 contentsRect 实现图片拼合,四个view的创建是使用sotryBoard中创建的,效果图如下:
代码实现:
UIImage *image = [UIImage imageNamed:@"宠物网_狗和鸭子.jpg"];
// set igloo sprite
[self addSpriteImage:image withContentRect:CGRectMake(0, 0, 0.5, 0.5) toLayer:self.coneView.layer];
// set cone sprite
[self addSpriteImage:image withContentRect:CGRectMake(0.5, 0, 0.5, 0.5) toLayer:self.shipView.layer];
// set anchor sprite
[self addSpriteImage:image withContentRect:CGRectMake(0, 0.5, 0.5, 0.5) toLayer:self.iglooView.layer];
// set spaceship sprite
[self addSpriteImage:image withContentRect:CGRectMake(0.5, 0.5, 0.5, 0.5) toLayer:self.anchorView.layer];
/// set image
- (void)addSpriteImage:(UIImage *)image withContentRect:(CGRect)rect toLayer:(CALayer *)layer {
layer.contents = (__bridge id)image.CGImage;
// scale contents to fit
layer.contentsGravity = kCAGravityResizeAspect;
// set contentsRect
layer.contentsRect = rect;
}
contentsCenter属性
如下图,展示了 contentsCenter设置为{0.25,0.25,0.5,0.5}的效果:
上一篇: 数据库学习实践(一)----系统登录
下一篇: 数据库实验四——嵌套SQL查询