CALayer上繪圖

在CALayer上繪圖有2種方法ios

1)建立一個CALayer的子類,而後覆蓋drawInContext:方法,可使用Quartz2D api進行繪圖api

2)設置CALayer的代理,讓代理實現drawLayer:inContext方法進行繪圖。通常是在控制器裏實現。這樣會增長控制器的負擔。iview

調用這2個方法之後都必須調用setNeedsDisplay方法從新繪製視圖,才能生效。函數

全部的非root layer都存在隱式動畫,根圖層沒有隱式動畫。負責UIVIEW部分。視圖上的根圖層是沒有隱式動畫的。動畫

 

 

 

1)採用代理方式在圖層上繪圖的代碼ui

 

//atom

//  MainViewController.mspa

//  CALayer繪圖_demo1代理

//code

//  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 <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);
    
    // 在形變座標系以前應該保存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的動畫效果好,就是把全部的圖層合成一個位圖來執行,這樣的效果會好。
相關文章
相關標籤/搜索