概覽
在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看到iOS中如何使用圖層精簡非交互式繪圖,如何通過核心動畫創建基礎動畫、關鍵幀動畫、動畫組、轉場動畫,如何通過UIView的裝飾方法對這些動畫操作進行簡化等。在今天的文章里您可以看到動畫操作在iOS中是如何簡單和高效,很多原來想做但是苦于沒有思路的動畫在iOS中將變得越發簡單:
- CALayer:
- CALayer簡介
- CALayer常用屬性
- CALayer繪圖
CALayer
1. CALayer簡介
在介紹動畫操作之前我們必須先來了解一個動畫中常用的對象CALayer。CALayer包含在QuartzCore框架中,這是一個跨平臺的框架,既可以用在iOS中又可以用在Mac OS X中。在使用Core Animation開發動畫的本質就是將CALayer中的內容轉化為位圖從而供硬件操作,所以要熟練掌握動畫操作必須先來熟悉CALayer。
使用Quartz 2D繪圖時大家其實已經用到了CALayer,當利用drawRect:方法繪圖的本質就是繪制到了UIView的layer(屬性)中,可是這個過程大家在上一節中根本體會不到。但是在Core Animation中我們操作更多的則不再是UIView而是直接面對CALayer。下圖描繪了CALayer和UIView的關系,在UIView中有一個layer屬性作為根圖層,根圖層上可以放其他子圖層,在UIView中所有能夠看到的內容都包含在layer中:
2. CALayer常用屬性
在iOS中CALayer的設計主要是了為了內容展示和動畫操作,CALayer本身并不包含在UIKit中,它不能響應事件。由于CALayer在設計之初就考慮它的動畫操作功能,CALayer很多屬性在修改時都能形成動畫效果,這種屬性稱為“隱式動畫屬性”。但是對于UIView的根圖層而言屬性的修改并不形成動畫效果,因為很多情況下根圖層更多的充當容器的做用,如果它的屬性變動形成動畫效果會直接影響子圖層。另外,UIView的根圖層創建工作完全由iOS負責完成,無法重新創建,但是可以往根圖層中添加子圖層或移除子圖層。
下表列出了CALayer常用的屬性:
屬性 | 說明 | 是否支持隱式動畫 |
---|---|---|
anchorPoint | 和中心點position重合的一個點,稱為“錨點”,錨點的描述是相對于x、y位置比例而言的默認在圖像中心點(0.5,0.5)的位置 | 是 |
backgroundColor | 圖層背景顏色 | 是 |
borderColor | 邊框顏色 | 是 |
borderWidth | 邊框寬度 | 是 |
bounds | 圖層大小 | 是 |
contents | 圖層顯示內容,例如可以將圖片作為圖層內容顯示 | 是 |
contentsRect | 圖層顯示內容的大小和位置 | 是 |
cornerRadius | 圓角半徑 | 是 |
doubleSided | 圖層背面是否顯示,默認為YES | 否 |
frame | 圖層大小和位置,不支持隱式動畫,所以CALayer中很少使用frame,通常使用bounds和position代替 | 否 |
hidden | 是否隱藏 | 是 |
mask | 圖層蒙版 | 是 |
maskToBounds | 子圖層是否剪切圖層邊界,默認為NO | 是 |
opacity | 透明度 ,類似于UIView的alpha | 是 |
position | 圖層中心點位置,類似于UIView的center | 是 |
shadowColor | 陰影顏色 | 是 |
shadowOffset | 陰影偏移量 | 是 |
shadowOpacity | 陰影透明度,注意默認為0,如果設置陰影必須設置此屬性 | 是 |
shadowPath | 陰影的形狀 | 是 |
shadowRadius | 陰影模糊半徑 | 是 |
sublayers | 子圖層 | 是 |
sublayerTransform | 子圖層形變 | 是 |
transform | 圖層形變 | 是 |
- 隱式屬性動畫的本質是這些屬性的變動默認隱含了CABasicAnimation動畫實現,詳情大家可以參照Xcode幫助文檔中“Animatable Properties”一節。
- 在CALayer中很少使用frame屬性,因為frame本身不支持動畫效果,通常使用bounds和position代替。
- CALayer中透明度使用opacity表示而不是alpha;中心點使用position表示而不是center。
- anchorPoint屬性是圖層的錨點,范圍在(01,01)表示在x、y軸的比例,這個點永遠可以同position(中心點)重合,當圖層中心點固定后,調整anchorPoint即可達到調整圖層顯示位置的作用(因為它永遠和position重合)
為了進一步說明anchorPoint的作用,假設有一個層大小100*100,現在中心點位置(50,50),由此可以得出frame(0,0,100,100)。上面說過anchorPoint默認為(0.5,0.5),同中心點position重合,此時使用圖形描述如圖1;當修改anchorPoint為(0,0),此時錨點處于圖層左上角,但是中心點poition并不會改變,因此圖層會向右下角移動,如圖2;然后修改anchorPoint為(1,1,),position還是保持位置不變,錨點處于圖層右下角,此時圖層如圖3。
下面通過一個簡單的例子演示一下上面幾個屬性,程序初始化階段我們定義一個正方形,但是圓角路徑調整為正方形邊長的一半,使其看起來是一個圓形,在點擊屏幕的時候修改圖層的屬性形成動畫效果(注意在程序中沒有直接修改UIView的layer屬性,因為根圖層無法形成動畫效果):
// KCMainViewController.m
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#define WIDTH 50
@interface KCMainViewController ()
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self drawMyLayer];
}
#pragma mark 繪制圖層
-(void)drawMyLayer{
CGSize size=[UIScreen mainScreen].bounds.size;
//獲得根圖層
CALayer *layer=[[CALayer alloc]init];
//設置背景顏色,由于QuartzCore是跨平臺框架,無法直接使用UIColor
layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
//設置中心點
layer.position=CGPointMake(size.width/2, size.height/2);
//設置大小
layer.bounds=CGRectMake(0, 0, WIDTH,WIDTH);
//設置圓角,當圓角半徑等于矩形的一半時看起來就是一個圓形
layer.cornerRadius=WIDTH/2;
//設置陰影
layer.shadowColor=[UIColor grayColor].CGColor;
layer.shadowOffset=CGSizeMake(2, 2);
layer.shadowOpacity=.9;
//設置邊框
// layer.borderColor=[UIColor whiteColor].CGColor;
// layer.borderWidth=1;
// 設置錨點
// layer.anchorPoint=CGPointZero;
[self.view.layer addSublayer:layer];
}
#pragma mark 點擊放大
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch=[touches anyObject];
CALayer *layer=self.view.layer.sublayers[0];
CGFloat width=layer.bounds.size.width;
if (width==WIDTH) {
width=WIDTH*4;
}else{
width=WIDTH;
}
layer.bounds=CGRectMake(0, 0, width, width);
layer.position=[touch locationInView:self.view];
layer.cornerRadius=width/2;
}
@end
運行效果:
3. CALayer繪圖
在使用Quartz 2D繪圖時,當調用了UIView的drawRect:方法繪制圖形、圖像,這種方式本質還是在圖層中繪制,但是這里會著重介紹一下如何直接在圖層中繪圖。在圖層中繪圖的方式跟原來基本沒有區別,只是drawRect:方法是由UIKit組件進行調用,因此里面可以使用一些UIKit封裝的方法進行繪圖,而直接繪制到圖層的方法由于并非UIKit直接調用因此只能用原生的Core Graphics方法繪制。
圖層繪圖有兩種方法,不管使用哪種方法繪制完必須調用圖層的setNeedDisplay方法(注意是圖層的方法,不是UIView的方法,前面我們介紹過UIView也有此方法)
- 通過圖層代理drawLayer: inContext:方法繪制
- 通過自定義圖層drawInContext:方法繪制
使用代理方法繪圖
通過代理方法進行圖層繪圖只要指定圖層的代理,然后在代理對象中重寫*-(void)drawLayer:(CALayer )layer inContext:(CGContextRef)ctx方法即可。需要注意這個方法雖然是代理方法但是不用手動實現CALayerDelegate,因為CALayer定義中給NSObject做了分類擴展,所有的NSObject都包含這個方法。另外設置完代理后必須要調用圖層的setNeedDisplay方法,否則繪制的內容無法顯示。
下面的代碼演示了在一個自定義圖層繪制一張圖像并將圖像設置成圓形,這種效果在很多應用中很常見,如最新版的手機QQ頭像就是這種效果:
//
// KCMainViewController.m
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#define PHOTO_HEIGHT 150
@interface KCMainViewController ()
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
//自定義圖層
CALayer *layer=[[CALayer alloc]init];
layer.bounds=CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
layer.position=CGPointMake(160, 200);
layer.backgroundColor=[UIColor redColor].CGColor;
layer.cornerRadius=PHOTO_HEIGHT/2;
//注意僅僅設置圓角,對于圖形而言可以正常顯示,但是對于圖層中繪制的圖片無法正確顯示
//如果想要正確顯示則必須設置masksToBounds=YES,剪切子圖層
layer.masksToBounds=YES;
//陰影效果無法和masksToBounds同時使用,因為masksToBounds的目的就是剪切外邊框,而陰影效果剛好在外邊框
// layer.shadowColor=[UIColor grayColor].CGColor;
// layer.shadowOffset=CGSizeMake(2, 2);
// layer.shadowOpacity=1;
//設置邊框
layer.borderColor=[UIColor whiteColor].CGColor;
layer.borderWidth=2;
//設置圖層代理
layer.delegate=self;
//添加圖層到根圖層
[self.view.layer addSublayer:layer];
//調用圖層setNeedDisplay,否則代理方法不會被調用
[layer setNeedsDisplay];
}
#pragma mark 繪制圖形、圖像到圖層,注意參數中的ctx是圖層的圖形上下文,其中繪圖位置也是相對圖層而言的
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
// NSLog(@"%@",layer);//這個圖層正是上面定義的圖層
CGContextSaveGState(ctx);
//圖形上下文形變,解決圖片倒立的問題
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -PHOTO_HEIGHT);
UIImage *image=[UIImage imageNamed:@"photo.png"];
//注意這個位置是相對于圖層而言的不是屏幕
CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage);
// CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
// CGContextDrawPath(ctx, kCGPathFillStroke);
CGContextRestoreGState(ctx);
}
@end
運行效果:
使用代理方法繪制圖形、圖像時在drawLayer:inContext:方法中可以通過事件參數獲得繪制的圖層和圖形上下文。在這個方法中繪圖時所有的位置都是相對于圖層而言的,圖形上下文指的也是當前圖層的圖形上下文。
需要注意的是上面代碼中繪制圖片圓形裁切效果時如果不設置masksToBounds是無法顯示圓形,但是對于其他圖形卻沒有這個限制。原因就是當繪制一張圖片到圖層上的時候會重新創建一個圖層添加到當前圖層,這樣一來如果設置了圓角之后雖然底圖層有圓角效果,但是子圖層還是矩形,只有設置了masksToBounds為YES讓子圖層按底圖層剪切才能顯示圓角效果。同樣的,有些朋友經常在網上提問說為什么使用UIImageView的layer設置圓角后圖片無法顯示圓角,只有設置masksToBounds才能出現效果,也是類似的問題。
擴展1--帶陰影效果的圓形圖片裁切
如果設置了masksToBounds=YES之后確實可以顯示圖片圓角效果,但遺憾的是設置了這個屬性之后就無法設置陰影效果。因為masksToBounds=YES就意味著外邊框不能顯示,而陰影恰恰作為外邊框繪制的,這樣兩個設置就產生了矛盾。要解決這個問題不妨換個思路:使用兩個大小一樣的圖層,下面的圖層負責繪制陰影,上面的圖層用來顯示圖片。
//
// KCMainViewController.m
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#define PHOTO_HEIGHT 150
@interface KCMainViewController ()
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGPoint position= CGPointMake(160, 200);
CGRect bounds=CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
CGFloat cornerRadius=PHOTO_HEIGHT/2;
CGFloat borderWidth=2;
//陰影圖層
CALayer *layerShadow=[[CALayer alloc]init];
layerShadow.bounds=bounds;
layerShadow.position=position;
layerShadow.cornerRadius=cornerRadius;
layerShadow.shadowColor=[UIColor grayColor].CGColor;
layerShadow.shadowOffset=CGSizeMake(2, 1);
layerShadow.shadowOpacity=1;
layerShadow.borderColor=[UIColor whiteColor].CGColor;
layerShadow.borderWidth=borderWidth;
[self.view.layer addSublayer:layerShadow];
//容器圖層
CALayer *layer=[[CALayer alloc]init];
layer.bounds=bounds;
layer.position=position;
layer.backgroundColor=[UIColor redColor].CGColor;
layer.cornerRadius=cornerRadius;
layer.masksToBounds=YES;
layer.borderColor=[UIColor whiteColor].CGColor;
layer.borderWidth=borderWidth;
//設置圖層代理
layer.delegate=self;
//添加圖層到根圖層
[self.view.layer addSublayer:layer];
//調用圖層setNeedDisplay,否則代理方法不會被調用
[layer setNeedsDisplay];
}
#pragma mark 繪制圖形、圖像到圖層,注意參數中的ctx是圖層的圖形上下文,其中繪圖位置也是相對圖層而言的
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
// NSLog(@"%@",layer);//這個圖層正是上面定義的圖層
CGContextSaveGState(ctx);
//圖形上下文形變,解決圖片倒立的問題
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -PHOTO_HEIGHT);
UIImage *image=[UIImage imageNamed:@"photo.jpg"];
//注意這個位置是相對于圖層而言的不是屏幕
CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage);
// CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
// CGContextDrawPath(ctx, kCGPathFillStroke);
CGContextRestoreGState(ctx);
}
@end
運行效果:
擴展2--圖層的形變
從上面代碼中大家不難發現使用Core Graphics繪制圖片時會倒立顯示,對圖層的圖形上下文進行了反轉。在前一篇文章中也采用了類似的方法去解決這個問題,但是在那篇文章中也提到過如果直接讓圖像沿著x軸旋轉180度同樣可以達到正確顯示的目的,只是當時的旋轉靠圖形上下文還無法繞x軸旋轉。今天學習了圖層之后,其實可以控制圖層直接旋轉而不用借助于圖形上下文的形變操作,而且這么操作起來會更加簡單和直觀。對于上面的程序,只需要設置圖層的transform屬性即可。需要注意的是transform是CATransform3D類型,形變可以在三個維度上進行,使用方法和前面介紹的二維形變是類似的,而且都有對應的形變設置方法(如:CATransform3DMakeTranslation()、CATransform3DMakeScale()、CATransform3DMakeRotation())。下面的代碼通過CATransform3DMakeRotation()方法在x軸旋轉180度解決倒立問題:
//
// 形變演示
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#define PHOTO_HEIGHT 150
@interface KCMainViewController ()
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGPoint position= CGPointMake(160, 200);
CGRect bounds=CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
CGFloat cornerRadius=PHOTO_HEIGHT/2;
CGFloat borderWidth=2;
//陰影圖層
CALayer *layerShadow=[[CALayer alloc]init];
layerShadow.bounds=bounds;
layerShadow.position=position;
layerShadow.cornerRadius=cornerRadius;
layerShadow.shadowColor=[UIColor grayColor].CGColor;
layerShadow.shadowOffset=CGSizeMake(2, 1);
layerShadow.shadowOpacity=1;
layerShadow.borderColor=[UIColor whiteColor].CGColor;
layerShadow.borderWidth=borderWidth;
[self.view.layer addSublayer:layerShadow];
//容器圖層
CALayer *layer=[[CALayer alloc]init];
layer.bounds=bounds;
layer.position=position;
layer.backgroundColor=[UIColor redColor].CGColor;
layer.cornerRadius=cornerRadius;
layer.masksToBounds=YES;
layer.borderColor=[UIColor whiteColor].CGColor;
layer.borderWidth=borderWidth;
//利用圖層形變解決圖像倒立問題
layer.transform=CATransform3DMakeRotation(M_PI, 1, 0, 0);
//設置圖層代理
layer.delegate=self;
//添加圖層到根圖層
[self.view.layer addSublayer:layer];
//調用圖層setNeedDisplay,否則代理方法不會被調用
[layer setNeedsDisplay];
}
#pragma mark 繪制圖形、圖像到圖層,注意參數中的ctx時圖層的圖形上下文,其中繪圖位置也是相對圖層而言的
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
// NSLog(@"%@",layer);//這個圖層正是上面定義的圖層
UIImage *image=[UIImage imageNamed:@"photo.jpg"];
//注意這個位置是相對于圖層而言的不是屏幕
CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage);
}
@end
事實上如果僅僅就顯示一張圖片在圖層中當然沒有必要那么麻煩,直接設置圖層contents就可以了,不牽涉到繪圖也就沒有倒立的問題了。
//
// 圖層內容設置
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#define PHOTO_HEIGHT 150
@interface KCMainViewController ()
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGPoint position= CGPointMake(160, 200);
CGRect bounds=CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
CGFloat cornerRadius=PHOTO_HEIGHT/2;
CGFloat borderWidth=2;
//陰影圖層
CALayer *layerShadow=[[CALayer alloc]init];
layerShadow.bounds=bounds;
layerShadow.position=position;
layerShadow.cornerRadius=cornerRadius;
layerShadow.shadowColor=[UIColor grayColor].CGColor;
layerShadow.shadowOffset=CGSizeMake(2, 1);
layerShadow.shadowOpacity=1;
layerShadow.borderColor=[UIColor whiteColor].CGColor;
layerShadow.borderWidth=borderWidth;
[self.view.layer addSublayer:layerShadow];
//容器圖層
CALayer *layer=[[CALayer alloc]init];
layer.bounds=bounds;
layer.position=position;
layer.backgroundColor=[UIColor redColor].CGColor;
layer.cornerRadius=cornerRadius;
layer.masksToBounds=YES;
layer.borderColor=[UIColor whiteColor].CGColor;
layer.borderWidth=borderWidth;
//設置內容(注意這里一定要轉換為CGImage)
UIImage *image=[UIImage imageNamed:@"photo.jpg"];
// layer.contents=(id)image.CGImage;
[layer setContents:(id)image.CGImage];
//添加圖層到根圖層
[self.view.layer addSublayer:layer];
}
@end
既然如此為什么還大費周章的說形變呢,因為形變對于動畫有特殊的意義。在動畫開發中形變往往不是直接設置transform,而是通過keyPath進行設置。這種方法設置形變的本質和前面沒有區別,只是利用了KVC可以動態修改其屬性值而已,但是這種方式在動畫中確實很常用的,因為它可以很方便的將幾種形變組合到一起使用。同樣是解決動畫旋轉問題,只要將前面的旋轉代碼改為下面的代碼即可:
[layer setValue:@M_PI forKeyPath:@"transform.rotation.x"];
當然,通過key path設置形變參數就需要了解有哪些key path可以設置,這里就不再一一列舉,大家可以參照Xcode幫助文檔中“CATransform3D Key Paths”一節,里面描述的很詳細。
使用自定義圖層繪圖
在自定義圖層中繪圖時只要自己編寫一個類繼承于CALayer然后在drawInContext:中繪圖即可。同前面在代理方法繪圖一樣,要顯示圖層中繪制的內容也要調用圖層的setNeedDisplay方法,否則drawInContext方法將不會調用。
在使用Quartz 2D在UIView中繪制圖形的本質也是繪制到圖層中,為了說明這個問題下面演示自定義圖層繪圖時沒有直接在視圖控制器中調用自定義圖層,而是在一個UIView將自定義圖層添加到UIView的根圖層中(例子中的UIView跟自定義圖層繪圖沒有直接關系)。從下面的代碼中可以看到:UIView在顯示時其根圖層會自動創建一個CGContextRef(CALayer本質使用的是位圖上下文),同時調用圖層代理(UIView創建圖層會自動設置圖層代理為其自身)的draw: inContext:方法并將圖形上下文作為參數傳遞給這個方法。而在UIView的draw:inContext:方法中會調用其drawRect:方法,在drawRect:方法中使用UIGraphicsGetCurrentContext()方法得到的上下文正是前面創建的上下文。
KCLayer.m
//
// KCLayer.m
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCLayer.h"
@implementation KCLayer
-(void)drawInContext:(CGContextRef)ctx{
NSLog(@"3-drawInContext:");
NSLog(@"CGContext:%@",ctx);
// CGContextRotateCTM(ctx, M_PI_4);
CGContextSetRGBFillColor(ctx, 135.0/255.0, 232.0/255.0, 84.0/255.0, 1);
CGContextSetRGBStrokeColor(ctx, 135.0/255.0, 232.0/255.0, 84.0/255.0, 1);
// CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
// CGContextFillEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));
CGContextMoveToPoint(ctx, 94.5, 33.5);
//// Star Drawing
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);
CGContextDrawPath(ctx, kCGPathFillStroke);
}
@end
KCView.m
//
// KCView.m
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCView.h"
#import "KCLayer.h"
@implementation KCView
-(instancetype)initWithFrame:(CGRect)frame{
NSLog(@"initWithFrame:");
if (self=[super initWithFrame:frame]) {
KCLayer *layer=[[KCLayer alloc]init];
layer.bounds=CGRectMake(0, 0, 185, 185);
layer.position=CGPointMake(160,284);
layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
//顯示圖層
[layer setNeedsDisplay];
[self.layer addSublayer:layer];
}
return self;
}
-(void)drawRect:(CGRect)rect{
NSLog(@"2-drawRect:");
NSLog(@"CGContext:%@",UIGraphicsGetCurrentContext());//得到的當前圖形上下文正是drawLayer中傳遞的
[super drawRect:rect];
}
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
NSLog(@"1-drawLayer:inContext:");
NSLog(@"CGContext:%@",ctx);
[super drawLayer:layer inContext:ctx];
}
@end
KCMainViewController.m
//
// KCMainViewController.m
// CALayer
//
// Created by Kenshin Cui on 14-3-22.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#import "KCView.h"
@interface KCMainViewController ()
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
KCView *view=[[KCView alloc]initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor=[UIColor colorWithRed:249.0/255.0 green:249.0/255.0 blue:249.0/255.0 alpha:1];
[self.view addSubview:view];
}
@end
運行效果: