美文网首页
[Core Animation] CALayer的寄宿图

[Core Animation] CALayer的寄宿图

作者: Minecode | 来源:发表于2017-12-24 20:37 被阅读0次

来自我的个人博客Minecode.link

寄宿图

我们都知道,视图可以导入图片,并设置其拉伸模式、放大比例之类。而图层也可以导入图片,CALayer提供了寄宿图的概念来实现这一点。简单来说,寄宿图就是图层之中包含的图。

CALayer的contents属性

在设置图层图片时,需要给contents赋值。其定义如下:
@property(nullable, strong) id contents;
可以看到,它是一个id类型的对象,但是这是为了兼容OSX开发中CoreAnimation、AppKit中的CGImage和NSImage两种类型而设置。对于UIKit的UIImage并不支持,设置了无法识别的对象是不能显示的,所以使用UIImage需要调用下述的转换方法:
- (nullable CGImageRef)CGImage
由于转换的是CGImageRef,我们知道C类型是不受ARC管理的,所以需要进行类型桥接。最终就是如下效果:
layer.contents = (__bridge id)image.CGImage;

contents相关属性

设置了寄宿图,我们还需要对其进行参数调整。图层在样式和动画方面提供了比视图更多的选择:

  • contentGravity  // 拉伸模式
  • contentsScale   // 像素比例
  • maskToBounds   // 是否裁切
  • contentsRect    // 显示区域
  • contentsCenter   // 拉伸区域

contentsGravity

当我们为content设置了图片后,图片默认是会拉伸至图层大小的,而如同视图的contetMode,图层为我们提供了contentGravity属性。
@property(copy) NSString *contentsGravity;
它是NSString类型,可选的常量值为kCAGravity**,具体如下

  • kCAGravityCenter
  • kCAGravityTop
  • kCAGravityBottom
  • kCAGravityLeft
  • kCAGravityRight
  • kCAGravityTopLeft
  • kCAGravityTopRight
  • kCAGravityBottomLeft
  • kCAGravityBottomRight
  • kCAGravityResize
  • kCAGravityResizeAspect
  • kCAGravityResizeAspectFill

对于图片被拉伸的问题,我们处理之后如下:


contentsGravity解决图片拉伸问题

contentsScale

由于苹果设备多采用了Retina屏幕,屏幕的实际分辨率(手机像素)和设计分辨率(视图的点)之间存在着区别。比如对于iPhone 6,视图大小为375×677(单位:点),但实际像素为750×1334(单位:像素),在界面开发时并无大碍,而对于图片素材,我们有时候不希望高分屏与图片的像素绘制比例为1:1,为了不让图片换算成视图大小后太小,就要设置实际缩放比,从而让高分屏用多个像素显示图片1个像素的内容。苹果为我们提供了contentsScale属性来设置。

比如当我们设置contentsScale为1.0,即屏幕每一个点绘制图片的1个像素。而contentsScale为2.0时,屏幕每一个点绘制图片的2个像素。显示效果如下:

contentsScale区别

Tips: 需要注意,缩放只有在图片适配模式不是kCAGravityResize***(拉伸)模式时才有效。

maskToBounds

这个属性对应视图的clipToBounds属性。默认情况下视图和图层都允许子视图和子图层的绘制范围超出自己的边界。但是很多情况下我们并不想要这个效果,很多样式都需要裁切子图层。效果如下:

masksToBounds效果

contentsRect

contentsRect用来指定内容显示的区域,比如显示图片的某个局部细节。注意数值是比例大小(0.0~1.0),而非视图大小。
其只是设置显示区域,而非裁剪图片,内存中保存的依旧是整个图片,如果要处理图片应使用Core Graphic。

contentsCenter

UIImage提供了resizableImageWithCapInsets方法来配置图片的拉伸,而在图层中可以通过设置ccontentsCenter属性来设置一个可拉伸区域,从而保证图片在收到拉伸时局部不变形。

我们选择一张聊天气泡的照片,然后编写如下代码来测试:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    UIImage *image = [UIImage imageNamed:@"bubble"];
    
    self.layerView1.layer.contents = (__bridge id)image.CGImage;
    self.layerView2.layer.contents = (__bridge id)image.CGImage;
    
    self.layerView2.layer.contentsCenter = CGRectMake(0.75, 0.75, 0.1, 0.1);
}

原图及裁切效果为:


气泡图 裁切后

通过Core Graphic绘制

CALayer除了通过Core Animation框架的属性来设置外,还可以直接通过Core Graphic来绘制。

UIView的显示机制

当视图在屏幕上出现时,它会检测-(void)rawRect:是否被实现(该方法无默认实现),如果实现了则为视图创建一个寄宿图,其大小等于视图大小×contentsScale。(若不实现该方法则不会创建,进而优化性能)。

-(void)drawRect:是视图的方法而不是图层的,图层提供了图层方法的代理,可由视图通过实现代理方法完成绘图。-(void)drawRect:不能手动调用,需要调用-(void)setNeedsDisplay来通知重绘。

调用-(void)setNeedsDisplay后会出发代理方法-(void)displayLayer:(CALayer *)layer和-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx。 (注:如果两种方法同时存在,则只会调用后者)。

相关文章

  • [Core Animation] CALayer的寄宿图

    来自我的个人博客Minecode.link 寄宿图 我们都知道,视图可以导入图片,并设置其拉伸模式、放大比例之类。...

  • Quartz 2D Coordinate Systems

    CALayer Core Animation --------------------------------- ...

  • Core Graphics & Core Animation

    架构图示 Core Graphics Core Animation CALayer presentationLay...

  • 第七篇:layer的隐式动画

    在Core Animation之CALayer一集中,我们介绍了Core Animation除了动画之外所有能做到...

  • CALayer与UIView之间的关系

    Core Animation在iOS系统中的关系图如下: UIView和CALayer是什么关系 1.首先UIVi...

  • 核心动画CoreAnimation

    核心动画作用在CALayer(Core animation layer)上,CALayer从概念上类似UIView...

  • 图层理解

    参看iOS-Core-Animation-Advanced-Techniques(一)参看CALayer与UIVi...

  • Core Animation

    基本概念 Core Animation 作用在 CALayer 上,CALayer从概念上类似UIView,每一个...

  • Core Animation

    CoreAnimation简介: Core Animation 使用步䠫: Core Animation类的继承图...

  • 核心动画二

    6> CoreAnimation Core Animation是直接作用在CALayer上的,并非UIView。C...

网友评论

      本文标题:[Core Animation] CALayer的寄宿图

      本文链接:https://www.haomeiwen.com/subject/mjohgxtx.html