• 010-CALayer(图层)


    问题一:什么是CALayer(图层)?

    简而言之:使UIView可以显示在屏幕上的功能属性,UIView之所以可以显示在屏幕上完全是因为UIView内部含有一个CALayer属性

    •在iOS中,能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView
     
    •UIView本身不具备显示的功能,之所以能显示完全是因为它内部的图层属性(具有显示功能)
     
    •在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
    @property(nonatomic,readonly,retain) CALayer *layer;
     
    •当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,将所有内容绘制在自己的图层上,绘图完毕后,系统将图层映射到屏幕上,于是就完成了UIView的显示
    // view的完整显示过程
    // 1. view.layer准备了一个Layer Graphics Context(图层类型的上下文)
    // 2. 调用view.layer.delegate(view)的drawLayer:inContext:,并传入刚才准备好的上下文
    // 3. view的drawLayer:inContext:方法内部又会调用view的drawRect:方法
    // 4. view就可以在drawRect:方法中实现绘图代码, 所有东西最终都绘制到view.layer上面
    // 5. 系统再将view.layer的内容拷贝到屏幕, 于是完成了view的显示

    问题二:CALayer具有哪些属性?

    九大属性:

    •1.内容(比如设置为图片CGImageRef)

    @property(retain) id contents;
    •2.位置(默认指中点,具体由anchorPoint决定)
    @property CGPoint position; // 用来设置CALayer在父层中的位置 以父层的左上角为原点(0, 0)
    •3.宽度和高度
    @property CGRect bounds;
    •4.锚点(x,y的范围都是0-1),决定了自身视图在position的坐落点
    @property CGPoint anchorPoint; // 称为“定位点”、“锚点” 决定着CALayer身上的哪个点会在position属性所指的位置 以自己的左上角为原点(0, 0) 它的x、y取值范围都是0~1,默认值为(0.5, 0.5)
    •5.背景颜色(CGColorRef类型)
    @property CGColorRef backgroundColor;
    •6.形变属性
    @property CATransform3D transform;
    •7.边框颜色(CGColorRef类型)
    @property CGColorRef borderColor;
    •8.边框宽度
    @property CGFloat borderWidth;
    •9.圆角半径
    @property CGColorRef borderRadius;

    问题三:CALayer可以用来做什么呢?

    •通过操作CALayer对象,可以很方便地调整UIView的一些外观属性,比如:
    Ø阴影
    Ø圆角大小
    Ø边框宽度和颜色
    Ø… …
    Ø代码示例:显示效果:
    - (void)testView
    {
        // 边框宽度
        self.purpleView.layer.borderWidth = 10;
        //    // 边框颜色
        self.purpleView.layer.borderColor = [UIColor blueColor].CGColor;
        // 圆角
        self.purpleView.layer.cornerRadius = 10;
        //    self.purpleView.layer.masksToBounds = YES; // 超出主层边框范围的内容都剪掉
        // 阴影颜色
        self.purpleView.layer.shadowColor = [UIColor blueColor].CGColor;
        // 阴影偏差
        self.purpleView.layer.shadowOffset = CGSizeMake(10, 10);
        // 阴影不透明度
        self.purpleView.layer.shadowOpacity = 0.5;
    }
    •还可以给图层添加动画,来实现一些比较炫酷的效果(见问题六)
    ps:新建图层
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // 新建图层
    //    CALayer *layer = [[CALayer alloc] init];
        CALayer *layer = [CALayer layer];
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.position = CGPointMake(200, 200);
        layer.anchorPoint = CGPointMake(1, 1);
        layer.cornerRadius = 10;
        layer.masksToBounds = YES;
        layer.contents = (id)[UIImage imageNamed:@"lufy"].CGImage;
        [self.view.layer addSublayer:layer];
        // 新建图层
        //    CALayer *layer1 = [[CALayer alloc] init];
        CALayer *layer1 = [CALayer layer];
        layer1.backgroundColor = [UIColor redColor].CGColor;
        layer1.bounds = CGRectMake(0, 0, 100, 100);
        layer1.position = CGPointMake(200, 200);
        layer1.anchorPoint = CGPointMake(0, 0);
        layer1.cornerRadius = 10;
        layer1.masksToBounds = YES;
        layer1.contents = (id)[UIImage imageNamed:@"lufy"].CGImage;
        [self.view.layer addSublayer:layer1];
    }
    新建图层

    ps:自定义图层

    @implementation WHBLayer
    /**
     *  只有明显地调用setNeedsDisplay方法,才会调用drawInContext:方法进行绘制
     */
    - (void)drawInContext:(CGContextRef)ctx
    {
        // 红色
        CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
        // 添加圆
        CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 50, 50));
        // 实心绘制
        CGContextFillPath(ctx);
    }
    WHBLayer.m
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        WHBLayer *layer = [WHBLayer layer];
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.backgroundColor = [UIColor greenColor].CGColor;
        layer.anchorPoint = CGPointZero;
        [layer setNeedsDisplay]; // 绘图 会自动调用WHBLayer的drawInContext:(CGContextRef)ctf 方法
        [self.view.layer addSublayer:layer];
    }
    ViewController.m

    问题四:为什么在CALayer中我们使用CGImageRef、CGColorRef两种数据类型来对其设置,而不用UIColor、UIImage???

    原因主要:考虑移植性,跨平台性

    •QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用 
      ØCALayer是定义在QuartzCore框架中的
      ØCGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的
    •但是UIKit只能在iOS中使用
      ØUIColor、UIImage是定义在UIKit框架中的
    •为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef

     问题五:既然UIView和CALayer均可在屏幕上显示图像,那又如何在二者之间做选择?

    •通过CALayer,就能做出跟UIImageView一样的界面效果
    •既然CALayer和UIView都能实现相同的显示效果,那究竟该选择谁好呢?
    Ø对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
    Ø如果显示出来的东西需要跟用户进行交互的话,用UIView;如果不需要跟用户进行交互,用UIView或者CALayer都可以
    Ø当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级

    问题六:如何利用CALayer来产生一些动画效果?什么是隐式动画?

    •所有手动创建的CALayer对象,都存在着隐式动画
    •什么是隐式动画?
    Ø当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果,称这些属性为Animatable Properties(可动画属性)
    •列举几个常见的Animatable Properties:
    // bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
    // backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
    // position:用于设置CALayer的位置。修改这个属性会产生平移动画
    •可以通过动画事务(CATransaction)关闭默认的隐式动画效果
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.myview.layer.position = CGPointMake(10, 10);
    [CATransaction commit];

     代码示例:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        CALayer *layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.position = CGPointZero;
        layer.anchorPoint = CGPointZero;
        [self.view.layer addSublayer:layer];
        self.layer = layer;
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        self.layer.backgroundColor = [UIColor blueColor].CGColor;
    //    [CATransaction begin]; // 开启事务
    //    [CATransaction setDisableActions:YES];
        
        self.layer.position = CGPointMake(100, 100);
        self.layer.opacity = 0.1;
        
    //    [CATransaction commit]; // 提交事务
    }
    隐式动画
     
     
  • 相关阅读:
    台达PLC开发笔记(二):台达PLC设置主机通讯参数为RTU并成功通讯
    台达PLC开发笔记(一):台达PLC连接介绍,分别使用485、网口与台达PLC建立连接
    Qt开发技术:图形视图框架(二)场景QGraphicsScene、QGraphicsItem与QGraphicsView详解
    Qt开发笔记:OpenSSL库介绍、windows上mingw32版本的OpenSSL编译模块化
    案例分享:Qt modbus485调试工具(读写Byte、Int、DInt、Real、DReal)(当前v1.3.0)
    案例分享:某品牌音响系列协议调试工具(搜寻主机,查询通道,基本控制API,云音乐API,语言节目API等,可增删改指令)
    stm32开发笔记(三):stm32系列的GPIO基本功能之输出驱动LED灯、输入按键KEY以及Demo
    stm32开发笔记(二):stm32系列使用V3.5固件库的帮助文件以及GPIO基本功能(一)
    Qt三方库开发技术(一):QuaZIP介绍、编译和使用
    NSIS制作安装包笔记(二):NSIS使用NSIS+Qt界面制作安装包流程
  • 原文地址:https://www.cnblogs.com/lszwhb/p/3928050.html
Copyright © 2020-2023  润新知