博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CALayer上绘图
阅读量:5884 次
发布时间:2019-06-19

本文共 5693 字,大约阅读时间需要 18 分钟。

在CALayer上绘图有2种方法

1)创建一个CALayer的子类,然后覆盖drawInContext:方法,可以使用Quartz2D api进行绘图

2)设置CALayer的代理,让代理实现drawLayer:inContext方法进行绘图。一般是在控制器里实现。这样会增加控制器的负担。

调用这2个方法以后都必须调用setNeedsDisplay方法重新绘制视图,才能生效。

所有的非root layer都存在隐式动画,根图层没有隐式动画。负责UIVIEW部分。视图上的根图层是没有隐式动画的。

 

 

 

1)采用代理方式在图层上绘图的代码

 

//

//  MainViewController.m

//  CALayer绘图_demo1

//

//  Created by mac on 13-10-1.

//  Copyright (c) 2013年 mac. All rights reserved.

//

 

#import "MainViewController.h"

#import <QuartzCore/QuartzCore.h>

 

@interfaceMainViewController ()

 

@end

 

@implementation MainViewController

 

- (void)viewDidLoad

{

    [superviewDidLoad];

// Do any additional setup after loading the view.

    

    

    // 创建一个layer

    CALayer *mylayer = [CALayer layer];

    [mylayer setBounds:CGRectMake(0, 0, 200, 200)];

    [mylayer setBackgroundColor:[UIColorredColor].CGColor];

    [mylayer setPosition:CGPointMake(100, 100)];

    [self.view.layer addSublayer:mylayer];

    

    // 这里不能将代理设置成view,因为view已经是根layer的代理,再设置一个图层的代理,会由冲突。

    // 通常让控制器来充当代理。如果代理多个图层,最好用一个标志区分开,也可以用tag来区分。

    [mylayer setDelegate:self];

    [mylayer setNeedsDisplay];

    NSLog(@"%@",mylayer);

}

 

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

{

    NSLog(@"%@",layer);

    CGRect rect = CGRectMake(50, 50, 100, 100);

    // 这2个方法都不起作用。不能使用uikit的方法

//    [[UIColor blueColor] set];

//    UIRectFill(rect);

    // 在Core animation里不能使用ui方法。

   // QuartzCore是夸平台的,这里只能使用C语言的函数,不能使用UIKIT方法

    CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);

    CGContextAddRect(ctx, rect);

    CGContextDrawPath(ctx, kCGPathFill);

}

 

@end

 显示结果

 

 

2) 自定义CALayer类,重写drawInContext方法来实现图层绘图

1.自定义layer,重写drawInContext方法

#import "MyLayer.h"

#import <QuartzCore/QuartzCore.h>

 

@implementation MyLayer

  // 从写drawInContext方法是关键,否则不能实现在自定义图层上绘图 

- (void)drawInContext:(CGContextRef)ctx

{

    // 绘制图层 绘制一个椭圆

  // 这里要用quartzcore方法,因为参数是CGContextRef,这个引用不能被uikit方法使用

    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 200));

    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);

    CGContextDrawPath(ctx, kCGPathFill);

}

 

@end

 

 

2.创建自定义视图,在自定义视图里实例化layer

- (id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        // Initialization code

        NSLog(@"init myview");

        MyLayer *mylayer = [MyLayer layer];

        // 要设置大小,否则不显示

        [mylayer setFrame:CGRectMake(0, 0, 100, 200)];

        [self.layer addSublayer:mylayer];

        [mylayer setNeedsDisplay];//添加到视图根图层以后,要调用自己的(图层)的setneedsdisplay方法

        self.mylayer = mylayer;

        

    }

    returnself;

}

 

3.在控制器根视图里创建自定义视图

- (void)viewDidLoad{    [super viewDidLoad];	// Do any additional setup after loading the view.        MyView *myview = [[MyView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];    [myview setBackgroundColor:[UIColor lightGrayColor]];    [self.view addSubview:myview];} 方法触发顺序 1.调用视图的init方法 2.在init方法里调用setneedsdisplay方法的时候,会触发代理的drawlayer方法,在drawlayer方法里要调用父类的drawlayer方法,这个会触发视图里的drawinrect方法。 3.然后调用视图的drawinrect方法 4.drawinrect方法再触发调用图层的drawincontext方法。 顺序 1)父视图的init方法 2)父视图的代理方法 3)父视图的drawinrect方法 4)子图层的drawincontext方法 使用代理方式绘图时,当uiview收到setneedsdisplay消息时,calayer会传出来一个cgcontextref引用。这时候可以在cgcontextref里进行绘图。 当使用自定义图层方式绘图时,当uiview收到setneedsdisplay消息时,uiview会调用自己的drawlayer方法,这个方法会调用自己的drawrect方法,这个方法再触发子图层的drawlayer方法。

 

 绘制图像

#import "MyLayer.h"

#import <QuartzCore/QuartzCore.h>

 

@implementation MyLayer

 

- (void)drawInContext:(CGContextRef)ctx

{

    // 绘制图层

    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));

    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);

    CGContextDrawPath(ctx, kCGPathFill);

    

    // 绘制图层

    CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 100, 100));

    CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);

    CGContextDrawPath(ctx, kCGPathFill);

    

    UIImage *image = [UIImage imageNamed:@"头像2.png"];

    CGContextDrawImage(ctx, CGRectMake(50, 50, 100, 100), image.CGImage);

}

 

@end

 结果

头像是反的。

这时候用到形变坐标系,但在形变坐标系之前,应该保存cgcontextref,形变坐标系之后,要恢复cgcontextref

//#import "MyLayer.h"#import 
@implementation MyLayer- (void)drawInContext:(CGContextRef)ctx{ // 绘制图层 CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100)); CGContextSetRGBFillColor(ctx, 1, 0, 0, 1); CGContextDrawPath(ctx, kCGPathFill); // 绘制图层 CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 100, 100)); CGContextSetRGBFillColor(ctx, 0, 1, 0, 1); CGContextDrawPath(ctx, kCGPathFill); // 在形变坐标系之前应该保存Context CGContextSaveGState(ctx); // 应该先翻转坐标系, // 否则会头像是反的 CGContextScaleCTM(ctx, 1.0, -1.0); CGContextTranslateCTM(ctx, 0, -self.bounds.size.height); UIImage *image = [UIImage imageNamed:@"头像2.png"]; CGContextDrawImage(ctx, CGRectMake(50, 50, 100, 100), image.CGImage); // 在形变坐标系之后要恢复context 这样不会影响以后的绘图 CGContextRestoreGState(ctx); }

 

 在uiview里添加了自定义图层以后,如果在图层里绘图,则uiview里本身的drawrect里的绘图会执行,但是会子图层的显示给覆盖掉

////  MyView.m//  CALayer自定义视图实现图层绘图////  Created by mac on 13-10-2.//  Copyright (c) 2013年 mac. All rights reserved.//#import "MyView.h"#import "MyLayer.h"@interface MyView ()@property (nonatomic,weak) MyLayer *mylayer;@end@implementation MyView- (id)initWithFrame:(CGRect)frame{    self = [super initWithFrame:frame];    if (self) {        // Initialization code        NSLog(@"init myview");        MyLayer *mylayer = [MyLayer layer];        [mylayer setBounds:self.bounds];        [mylayer setPosition:CGPointMake(100, 100)];        [self.layer addSublayer:mylayer];        [mylayer setNeedsDisplay];        self.mylayer = mylayer;            }    return self;}// 这个代码是执行的,但是结果会被子图层的显示给覆盖掉- (void)drawRect:(CGRect)rect{    // Drawing code        CGContextRef context = UIGraphicsGetCurrentContext();    CGContextAddRect(context, CGRectMake(50, 50, 20, 20));    CGContextDrawPath(context, kCGPathFill);}@end 如果使用了calayer的绘图就不要再使用视图的drawrect的绘图方法,即使用了,也会被layer的绘图显示给覆盖掉。 CGContextRef是位图的上下文。动画就是把所有的图层和到一个CGContextRef,位图上下文里。提高动画执行效率。 ios的动画效果好,就是把所有的图层合成一个位图来执行,这样的效果会好。

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/damao2012/p/3348837.html

你可能感兴趣的文章
高性能 Oracle JDBC 编程
查看>>
java 中ResultSet可以获取的数据类型及返回值类型列表
查看>>
ubuntu 13 安装SH程序
查看>>
支付宝升级延时到账功能
查看>>
ghost后只剩下一个盘的数据寻回方法
查看>>
输入输出练习
查看>>
Git commit message和工作流规范
查看>>
java面试。答案源于网上
查看>>
yii中取得CActiveDataProvider的分页信息
查看>>
我的大学
查看>>
Google翻译接口收费啦
查看>>
Debian+Apache2服务器
查看>>
MySQL库和表的操作
查看>>
shell编程:编译器、解释器 变量
查看>>
yum仓库一些简单介绍
查看>>
HashMap----工作原理
查看>>
nodejs 安装 postgresql module
查看>>
【转】iOS学习之iOS禁止Touch事件
查看>>
【小记录】解决链接libcufft_static.a库出现的错误
查看>>
两列布局的几种实现方案
查看>>