欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

XZ_iOS之核心动画高级技巧之给UIView设置图片

程序员文章站 2022-05-08 17:03:59
...

    在 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 的属性:

XZ_iOS之核心动画高级技巧之给UIView设置图片

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中创建的,效果图如下:

XZ_iOS之核心动画高级技巧之给UIView设置图片

代码实现:

    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}的效果:

XZ_iOS之核心动画高级技巧之给UIView设置图片