【iOS提高】CoreAnimation--Layer

前言

     iOS中能看见的东西都是view 比如一个按钮 一个文本标签等。UIView之所以能显示在屏幕上 完全是因为内部的图层。

     在创建UIView对象时 UIView内部会自动创建一个图层 CALayer对象 通过UIView的layer属性可以访问这个层

     当UIView需要显示到屏幕上 会调用drawRect方法绘图 并且将所有内容绘制到自己图层上 绘图完毕 系统会将图层拷贝到屏幕上。于是就完成了UIView的显示。换句话 UIView本身不具有显示的功能。


CALayer简单使用

iOS6之前需要导入QuartzCore.framework。之后不需要 Xcode自动导入了。

1.属性设置

-(void)addView
{
    CGRect rect = CGRectMake(10, 50, 100, 100);
    UIView * view = [[UIView alloc]initWithFrame:rect];
    [self.view addSubview:view];
    //设置
    view.layer.borderColor = [UIColor redColor].CGColor; //边框颜色
    view.layer.borderWidth = 14;//边框宽度
    view.layer.cornerRadius = 10;//圆角设置
    view.layer.shadowColor = [UIColor blueColor].CGColor;//阴影颜色
}
-(void)addImageView
{
    CGRect rect = CGRectMake(10, 200, 100, 100);
    UIImageView * imgView = [[UIImageView alloc]initWithFrame:rect];
    [self.view addSubview:imgView];
    imgView.image = [UIImage imageNamed:@"123.jpg"];
    //边框颜色
    imgView.layer.borderColor = [UIColor redColor].CGColor;
    //边框宽度
    imgView.layer.borderWidth = 14;
    //圆角大小
    imgView.layer.cornerRadius = 10;
    //阴影颜色
    imgView.layer.shadowColor = [UIColor blueColor].CGColor;
    //图片无圆角 是因为图片所在的layer非主层。设置超出范围剪切掉。
    imgView.layer.masksToBounds = YES;
    
    //旋转
    imgView.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
//    NSValue * value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)];
//    [imgView.layer setValue:value forKey:@"transform"];
//    [imgView.layer setValue:@(M_PI_4) forKey:@"transform.rotation"];
    //缩放
//    imgView.layer.transform = CATransform3DMakeScale(0.5, 2, 0);
//    [imgView.layer setValue:@(0.5) forKey:@"transform.scale.x"];
    //平移
//    imgView.layer.transform = CATransform3DMakeTranslation(100, 20, 10);
    NSValue * translationSize = [NSValue valueWithCGSize:CGSizeMake(-100, -100)];
    [imgView.layer setValue:translationSize forKey:@"translation"];
    //该方法后面的key可以设置为各种的值:
    /*
    rotation      rotation.x      rotation.y      rotation.z
    scale           scale.x          scale.y          scale.z
    transform  transform.x  transform.y transform.z
    translation
     */
}

新建CALayer

    

CALayer * layer = [CALayer layer];
    [self.view.layer addSublayer:layer];
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.position = CGPointMake(200, 100);
    
    UIImage * image = [UIImage imageNamed:@"123.jpg"];
    layer.contents = (id)image.CGImage;


     对比CALayer UIView多了一个事件处理功能 也就是说 CALayer不能处理用户的触摸事件 而UIView可以。

     因此 如果需要事件交互 用UIView 否则用CALayer。CALayer性能更高一点。

     

有关CALayer

     CALayer是定义在QuartzCore框架中的。

     CGImageRef CGColorRef两种数据类型是定义在CoreGraphics框架中的

     UIColor UIImage是定义在UIKit框架中的。

     QuartzCore框架和CoreGraphics框架是可以跨平台使用 在iOS和Mac OSX上都能使用

     但是UIKit只能在iOS中使用。

CALayer的两个重要的属性 position和anchorPoint

    

        @property CGPoint position 

//设置CALayer在父层的位置 以父层的左上角为原点(0,0)

        @property CGPoint anchorPoint;锚点

      //决定这CALayer的哪个点会在position所指的位置。

      //以自己的左上角为原点(0,0) x y 取值范围都是0-1 默认值为(0.5,0.5)

     CALayer的隐式动画

     每一个UIView内部都默认关联一个CALayer 我们可以称这个Layer为Root Layer(根层)

     所有的非Root Layer也就是手动创建的CALayer对象 都存在隐式动画。

     当对非RootLayer得部分属性进行修改时 默认会自动产生一些动画效果

     而这些属性称为Animatable Properties(可动画属性)

      常见的可动画属性:

     bounds:用于设置CALayer的宽度和高度 修改这个属性会产生缩放动画

     backgroundColor:用于设置CALayer的背景色 修改这个属性会产生背景色渐变动画

    

CALayer * layer = [[CALayer alloc]init];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.position = CGPointMake(100, 100);
//    layer.anchorPoint = CGPointMake(10, 10);
    [self.view.layer addSublayer:layer];
    layer.opacity = 0.5;
    _layer = layer;
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [CATransaction begin];
    self.layer.opacity = 1;
    [CATransaction setDisableActions:YES];
    self.layer.backgroundColor = [UIColor blueColor].CGColor;
    
    self.layer.position = CGPointMake(0,0);
    [CATransaction commit];
}

自定义CALayer

1.创建类继承自CALayer 然后重写drawInContext方法

-(void)drawInContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 1,0,0,1);
    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 50, 50));
    CGContextFillPath(ctx);
}

在控制器实现方法:

-(void)test1
{
    //当前没有出现圆形 给定颜色 发现layer出现而圆形没有。
    //显式调用setNeedsDisplay 出现
    //只有明显滴调用setNeedsDisplay 才能调用drawIncontext方法。
    MyLayer * layer =[[ MyLayer alloc]init];
    layer.frame = CGRectMake(0, 0, 100, 100);
    [layer setNeedsDisplay];
    layer.backgroundColor = [UIColor blueColor].CGColor;
    [self.view.layer addSublayer:layer];
}

第二种方法:指定view的代理为当前控制器,重写方法drawLayer:InContext

-(void)test2
{
    //代理帮我画
    CALayer * layer = [[CALayer alloc]init];
    layer.frame = CGRectMake(0, 0, 100, 100);
    layer.backgroundColor = [UIColor blueColor].CGColor;
    layer.position = CGPointMake(100, 100);
    layer.anchorPoint = CGPointZero;
    [self.view.layer addSublayer:layer];
    //指定代理方法
    layer.delegate = self;
    //当前指定代理 不需要遵守协议 那么 该代理是所有的对象都可以当我的代理
    //测试后发现当前的layer上并没有圆形 debug后发现代理方法并没有执行。
    //答案:想要画东西 必须显式调用setNeedsDisplay方法
    [layer setNeedsDisplay];
}

#pragma mark - layer的代理方法
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    NSLog(@"%@",@"是否");
    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
    CGRect rect = CGRectMake(0, 0, 30, 30);
    CGContextAddEllipseInRect(ctx, rect);
    CGContextFillPath(ctx);
}



UIView完整的显示过程:

当UIview需要显示时,

1.内部的layer会准备好一个CGContext上下文

2.然后调用delegate的方法drawLayer:InContext方法。如果当前view设置代理为当前的控制器 必须重写drawLayer方法,

3.在调用drawLayer:InContext方法之后,会调用view自己的drawInRect方法。传入的Context绘图完毕,被拷贝到屏幕。














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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值