CALayer的寄宿图

来源:互联网 发布:python图片验证码识别 编辑:程序博客网 时间:2024/05/05 11:10

来自我的个人博客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。 (注:如果两种方法同时存在,则只会调用后者)。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 掘进机截齿型号 齿的 回收截齿 采煤机截齿座 宁东斗齿 截齿等离子堆焊机 截齿焊接生产线 掘进机截齿座 什么是截齿 齿禹念什么 煤机截齿型号 裂齿 截根 戬怎么读 食戬之灵 慕容秋雨黎戬全文阅读 安音秦戬 食戬之灵第四季 食戬之灵第三季 食戬之我有万界食材 爱戬基地吧 戬空吧 戬空 帝戬吧 帝戬玉帝对杨戬用药 食戬之灵第二季 食戬之灵4 戬心 戬心吧 戬心同人 戬心之子西海小太子 戬心之春风吹又生 戬心之给宝宝找个爹 戬心生子文我娘叫寸心 戬心生子文我爹是杨戬 戬心之寸心之子沧儿 戬心家有小龙 戬心之守护爱情 戬心吧之寸心我爱你 戬心生子无意便休小龙杨旦