CALayer学习笔记

2020-02-29  本文已影响0人  Arthur澪

简介

在iOS系统中,看得见摸得着的基本都是UIView,如一个按钮、一个文本标签等,这些都是UIView。它能显示在屏幕上,是因为它内部的一个层,即CALayer对象。CALayer是被定义在QuartzCore框架中的,并不包含在UIKit中,它不能响应事件。

基本使用

通过操作这个CALayer对象,可以设置UIView的一些界面属性,如:阴影、圆角大小、边框宽度和颜色等。

imgv.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);

M_PI_4表示四分之π,顺时针旋转45°
后面的(0, 0, 1)表示Z轴这个向量,修改这个向量可以做一些三维旋转效果。总体的意思是layer会绕着Z轴顺时针旋转45°,即在x、y平面进行旋转。

常用属性

-
    UIImage *img = [UIImage imageNamed:@"xxx"];
    layer.contents = (id)img.CGImage;

cornerRadius
hidden
shadowColor
shadowOffset 阴影偏移量
shadowOpacity
阴影透明度,注意默认为0,如果设置阴影必须设置此属性
shadowPath
阴影形状,CGPathRef类型
shadowRadius

阴影效果无法和masksToBounds同时使用,因为masksToBounds是剪切外边框,而阴影效果刚好在外边框。

图层操作

// 添加子图层
- (void)addSublayer:(CALayer *)layer; 

//将自己从父图层中移除
- (void)removeFromSuperlayer; 

//在自己子图层数组中的第idx位置添加图层
- (void)insertSublayer:(CALayer *)layer atIndex:(unsigned)idx; 

//将图层layer添加在子图层sibling的下面
- (void)insertSublayer:(CALayer )layer below:(nullable CALayer )sibling; 

//将图层layer添加在子图层sibling的上面
- (void)insertSublayer:(CALayer )layer above:(nullable CALayer )sibling; 

//将图层layer替换layer2;
- (void)replaceSublayer:(CALayer )layer with:(CALayer )layer2; 

动画操作

//图层添加某一属性的动画
- (void)addAnimation:(CAAnimation )anim forKey:(nullable NSString )key; 

//获取所有动画的属性
- (nullable NSArray< NSString > )animationKeys; 

//获取某一属性的动画
- (nullable CAAnimation )animationForKey:(NSString )key; 

//移除某一属性动画
- (void)removeAnimationForKey:(NSString *)key; 

//移除所有动画
- (void)removeAllAnimations; 

隐式动画

在iOS中CALayer的设计主要是为了内容展示和动画操作。CALayer的很多属性在修改时,都能形成动画效果。这种属性称为隐式动画属性。

但不是每个属性都支持隐式动画。看看属性声明,有Animatable注释的才支持。
隐式属性动画的本质是,这些属性的变动默认隐含了CABasicAnimation动画实现

但是对于UIView的根视图层而言,属性的修改并不形成动画效果,因为很多情况下根图层更多的充当容器的作用。另外,UIView的根图层创建工作完全有iOS负责完成,无法重新创建。

    CALayer *la = [[CALayer alloc] init];
    la.backgroundColor = [UIColor redColor].CGColor;
    la.cornerRadius = 10;
    la.position = CGPointMake(100, 100);
    la.bounds = CGRectMake(0, 0, 100, 100);
    
    [self.view.layer addSublayer:la];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        la.position = CGPointMake(230, 230);   // 改变属性 position
    });

CALayer绘图

使用Quartz 2D绘图,是直接调用UIView的drawRect:方法绘制图形、图像,这种方式的本质还是再图层中绘制。drawRect:方法是由UIKit组件进行调用,因此厘米那可以使用到一些UIKit封装的方法进行绘制。而直接绘制到图层的方法并非UIKit直接调用,因此只能用原生的Core Graphics方法绘制。

1、通过图层代理drawLayer:inContext:方法绘制

通过代理方法进行图层绘制,只要指定图层的代理,然后在代理对象中重写- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;即可。

例子:把图片绘制在一个layer上

// 遵守协议 <CALayerDelegate>

- (void)viewDidLoad {
    // PHOTO_HEIGHT 为长度
    CALayer *layer = [[CALayer alloc] init];
    layer.bounds = CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
    layer.position = CGPointMake(160, 200);
    layer.cornerRadius = PHOTO_HEIGHT/2;
    layer.masksToBounds = YES;
    
    layer.delegate = self;
   
    [self.view.layer addSublayer:layer];
    // 调用setNeedsDisplay。否则代理方法不会被调用
    [layer setNeedsDisplay];
}

#pragma mark 代理方法 - 绘制图形、图像到图层,参数中的ctx是图层的图形上下文
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
    //这个图层就是上面定义的图层layer
    CGContextSaveGState(ctx);
    
    //图形上下文形变,解决图片倒立的问题
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -PHOTO_HEIGHT);
    
    //注意这个位置是相对于图层而言的,不是屏幕.
    CGRect ff = CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
    //把图片绘制到layer上
    UIImage *image = [UIImage imageNamed:@"xxx"];
    CGContextDrawImage(ctx, ff, image.CGImage);
    
    CGContextRestoreGState(ctx);
}

2、使用自定义图层绘图

只要编写一个类继承自CALayer,然后重写- (void)drawInContext:(CGContextRef)ctx;方法,在其中绘图即可。

例如,绘制星星
创建一个CALayer的子类KCALayer。

-(void)drawInContext:(CGContextRef)ctx{
    // 绘制一个正方形
//    CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
    // 绘制一个椭圆形
//    CGContextFillEllipseInRect(ctx, CGRectMake(50, 50, 150, 100));
    // 自定义绘制一个星星
    CGContextMoveToPoint(ctx, 94.5, 33.5);
    CGContextAddLineToPoint(ctx,104.02, 47.39);
    CGContextAddLineToPoint(ctx,120.18, 52.16);
    CGContextAddLineToPoint(ctx,109.91, 65.51);
    CGContextAddLineToPoint(ctx,110.37, 82.34);
    CGContextAddLineToPoint(ctx,94.5, 76.7);
    CGContextAddLineToPoint(ctx,78.63, 82.34);
    CGContextAddLineToPoint(ctx,79.09, 65.51);
    CGContextAddLineToPoint(ctx,68.82, 52.16);
    CGContextAddLineToPoint(ctx,84.98, 47.39);
    CGContextClosePath(ctx);
    
    // 图形填充颜色
    CGContextSetRGBFillColor(ctx, 0/255.0, 232.0/255.0, 84.0/255.0, 1);
    CGContextSetRGBStrokeColor(ctx, 0/255.0, 232.0/255.0, 84.0/255.0, 1);
    
    CGContextDrawPath(ctx, kCGPathFillStroke);
}

外界使用

- (void)viewDidLoad {
    KCALayer *layer = [[KCALayer alloc] init];
    layer.backgroundColor = [UIColor yellowColor].CGColor;
    layer.bounds = CGRectMake(0, 0, 185, 185);
    layer.position = CGPointMake(160,284);
    
    //显示图层
    [layer setNeedsDisplay];
    
    [self.view.layer addSublayer:layer];
}
-
上一篇 下一篇

猜你喜欢

热点阅读