UIView 的 layer

iOS 中能看得见的控件基本都是 UIView,比如按钮、文本、输入框、图片等等。

UIView 之所以能显示在屏幕上,因为它内部有一个图层:CALayer

@property(nonatomic,readonly,retain) CALayer *layer;
复制代码

当 UIView 显示在屏幕上的时候,会调用 drawRect: 方法进行绘图,会将所有的内容绘制在自己的图层上,绘制完毕后,系统会将图层拷贝到屏幕上,于是 UIView 就显示了出来。

通过下面的方法可以获取到 view 的图层。

CALayer *layer = self.view.layer;
复制代码

一个 UIView 只有一个 layer 属性,但是 layer 是可以叠加的,多个 layer 叠加在一起就构成了一个组合图像。

添加图层

一个图层可以有多个子图层。在绘制屏幕的时候,子图层可以被排列后固定在一起。

比如游戏图层,一个绘制背景,一个绘制角色,一个绘制地图。

可以为每个图层准备一个专门的 UIView,然后用另外一个 UIView 来整合图层:

// 整合的 UIView 类
UIView *gameView = [[UIView alloc]initWithFrame:[[UIScreen mainScreen] applicationFrame]];  
// 背景图层
UIView *backgroundView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];  
// 角色图层
UIView *roleView= [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 200.0)];  
// 地图图层
UIView *mapView = [[UIView alloc] initWithFrame:CGRectMake(200.0, 0.0, 100.0, 100.0)];  

//通过CALayer 类的addSublayer 方法,可以将3个UIView 类的图层全都与 gameView 对象链接在一起 
CALayer* gameLayer = gameView.layer;  
[gameLayer addSublayer:backgroundView.layer];  
[gameLayer addSublayer:roleView.layer];  
[gameLayer addSublayer:mapView.layer]; 
复制代码

当 gameView 对象显示在屏幕上的时候,3个子图层被合并在一起绘制出来。每个类单独绘制他自己的图层,但当游戏图层被显示出来的时候,3个图层就全都融合在一起了。

子图层也可以添加自己的子图层,并且可以构建一个完整的图层层次结构。

//mapView图层中再构加入一个图层,用来显示剩余里程数
UILabel *lastDistance = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 20.0, 20.0)];  
[mapView.layer addSublayer:lastDistance.layer]; 
复制代码

通过设置图层的position属性,你还可以不用改变图层的大小就对其位置进行调整。这个属性接受一个CGPoint 结构体,来定位图层在屏幕上的偏移位置。与frame 属性不同,position 属性指定的是图层的重点,而不是左上角:

CGPoint lastDistancePosition = CGPointMake(100.0, 100.0);  
lastDistance.layer.position = lastDistancePosition;
复制代码

可以使用 addSublayer讲图层添加到其他图层的顶层,也可以使用 insertSublayer将图层插入到现有的图层之间。

使用 avove 或者 below 参数,可以将图层插入到指定图层的上面或者下面:

[gamelayer insertSublayer:mapView.layer below:backgroundView.layer];  

[gamelayer insertSublayer:mapView.layer above:roleView.layer]; 
复制代码

使用 removeFromSuperlayer 方法可以将图层从父图层上移除。

使用 replaceSublayer 可以替换某个图层

[gamelayer replaceSublayer:backgroundView.layer with:newBackgroundView.layer ]; 
复制代码

layer 同样有 hidden 属性,可以保留在父图层的同时,将它隐藏。

图层绘制

在更新一个图层时,变化不是立刻被绘制在屏幕上的。这样就可以对图层做很多写操作而不会被展示给用户,直到所有的操作全部结束为止。当图层准备好可以进行重画时,就调用图层的 setNeedsDisplay 方法:

[gamelayer setNeedsDisplsy];
复制代码

有时候不需要重绘整个图层,只需要重新绘制某一部分,就可以使用 setNeedsDisplayInRect::

CGRect mapViewFrame = CGRectMake(150.0, 150.0, 75.0, 75.0);  
[gameLayer setNeedsDisplayInRect:mapViewFrame];
复制代码

可以使用 transform 或者 affineTransform 属性对 layer 进行变换

roleview.layer.transform = CATransform3DMakeScale(-1.0, -1.0, 1.0);  
CGAffineTransform transform = CGAffineTransformMakeRotation(45.0);  
backgroundView.layer.affineTransform = transform ; 
复制代码

动画

结合 Core Animation 可以创建出很多的动画效果。

例如转场动画:

CATransition* animation = [[CATransition alloc]init];  
 animation.duration =1.0;  
 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];  
 animation.type = kCATransitionPush;  
 animation.subtype = kCATransitionFromRight;
复制代码

CABasicAnimation 旋转动画

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];  
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(3.1415, 0, 0, 1.0)];  
animation.duration = 3.0;  
animation.cumulative = YES;  
animation.repeatCount = 2; 
复制代码

创建好之后,你可以直接将动画或者转场应用到一个图层上

[mapView.layer addAnimation:animation forKey:@"animation"];  
复制代码

Quartz Core 的渲染能力可以像三维一样对二维图像进行任意操纵。一个图像可以在 x-y-z 三维轴上进行任意角度旋转、缩放和扭曲。

变换是在单独的图层上执行的,因此多个变换可以在一个图层表面上同时进行。

Quartz Core 框架用 CATransform3D 对象来执行变换。这个对象作用于视图的图层,根据期望的三维设置对图层进行弯折或者其他操作。

对一个图层进行 3D 旋转:

CATransform3D myTransform;  
myTransform = CATransform3DMakeRotation(angle,x,y,z);  
复制代码

CATransform3DMakeRotation 函数创建了一个变换,对一个图形进行旋转,旋转角度angle单位为弧度,轴为 x-y-zx-y-z的值定义了轴上在各个方向上的度量(介于-1和+1之间)。在一个轴上赋予值,就会指示变换绕该轴进行旋转。

要将一个图层绕水平轴转动(垂直转动)45度,可以使用下面的代码:

myTransform = CATransform3DMakeRotation(0.78, 1.0, 0.0, 0.0);
//0.78 是角度45度换成弧度得到的  
复制代码

要在水平方向上转动同样的角度,可以换成 y 轴指定一个值:

myTransform = CATransform3DMakeRotation(0.78, 0.0, 1.0, 0.0); 
复制代码

CALayer 对象提供了一个 transform属性,可以用来将变换附加到图层之上。

roleView.layer.transform = myTransform; 
复制代码

转载于:https://juejin.im/post/5a93c94cf265da4e914b8339

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值