CALayer基礎(chǔ)

轉(zhuǎn)載:http://www.reibang.com/p/18c306333080

1.UIView與CALayer的關(guān)系:

CALayer在概念上和UIView類似胶惰,同樣也是一些被層級關(guān)系樹管理的矩形塊篓足,同樣也可以包含一些內(nèi)容(像圖片啼肩,文本或者背景色)忆首,管理子圖層的位置够话。并且它們有一些方法和屬性用來做動畫和變換担汤,但是CALayer不能響應(yīng)事件壤巷。

UIView是基于CALayer的一種封裝,每一個UIView都有一個CALayer實(shí)例的圖層屬性铭段,也就是所謂的backing layer骤宣,視圖的職責(zé)就是創(chuàng)建并管理這個圖層,以確保當(dāng)子視圖在層級關(guān)系中添加或者被移除的時候序愚,他們關(guān)聯(lián)的圖層也同樣對應(yīng)在層級關(guān)系樹當(dāng)中有相同的操作憔披。UIView的尺寸樣式以及內(nèi)容都由CALayer提供。

大多數(shù)情況下我們都使用UIView而不使用CALayer的原因是爸吮,首先是CALayer不能響應(yīng)事件芬膝,其次是CALayer不方便自動布局,最重要的是蘋果已經(jīng)基于CALayer封裝好了UIView拗胜,我們在使用UIView高級接口的同時也能使用CALayer的底層功能蔗候。

既然這里提到了層級樹,順便提一下事件響應(yīng)鏈

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{

UIResponder* next = [selfnextResponder];

NSMutableString* prefix =@"-".mutableCopy;

while(next !=nil) {

? ? ? ? ? NSLog(@"%@%@", prefix, [nextclass]);? ?

? ? ? ? ? ?[prefix appendString:@"--"];? ? ?

? ? ? ? ? ?next = [next nextResponder];? }

}

2. CALayer內(nèi)容相關(guān)的屬性

contents

可以給CALayer的contents賦值

self.layerView.layer.contents= (__bridgeid)image.CGImage;

contentGravity

可以類似設(shè)置UIView的contentModel一樣埂软,設(shè)置CALayer的contentGravity

self.layerView.layer.contentsGravity = kCAGravityResizeAspect;

contentGravity可以賦值的常量值如下

CA_EXTERNNSString*constkCAGravityCenterCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityTopCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityBottomCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityLeftCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityRightCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityTopLeftCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityTopRightCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityBottomLeftCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityBottomRightCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityResizeCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityResizeAspectCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityResizeAspectFillCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);

contentsScale

CALayer的contentsScale屬性可以用以適配retina屏幕锈遥,該屬性值默認(rèn)為1.0纫事,將會以每個點(diǎn)1個像素繪制圖片,如果設(shè)置為2.0所灸,則會以每個點(diǎn)2個像素繪制圖片丽惶,這就是我們熟知的Retina屏幕。

UIImage*image = [UIImageimageNamed:@"doll"];UIView*view = [[UIViewalloc] initWithFrame:self.view.bounds];view.layer.contents = (__bridgeid_Nullable)(image.CGImage);view.layer.contentsGravity = kCAGravityCenter;[self.view addSubview:view];

運(yùn)行結(jié)果:

6CC1E4E8-6490-4586-BFA6-B146EC440776.png

可以看到顯示出來的圖片有像素顆粒感爬立,在上面代碼的基礎(chǔ)上再加上一句

view.layer.contentsScale = [UIScreen mainScreen].scale;

運(yùn)行結(jié)果:

B01FE8E0-7E06-4BA3-A95D-99D1F5BFC1CD.png

maskToBounds

類似UIView的clipsToBounds钾唬,CALayer有一個屬性叫maskToBounds

self.layerView.layer.masksToBounds =YES;

contentsRect

CALayer的contentsRect屬性可以用于圖片拼合

舉個栗子,有如下圖片:

doll@2x.png

我們可以利用contentsRect屬性來分別單獨(dú)顯示三個娃娃:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*leftTopImage;@property(weak,nonatomic)IBOutletUIView*rightTopImage;@property(weak,nonatomic)IBOutletUIView*leftBottomImage;@end@implementationViewController-(void)viewDidLoad {? ? ? [superviewDidLoad];UIImage*image = [UIImageimageNamed:@"doll"];self.leftTopImage.layer.contents = (__bridgeid_Nullable)(image.CGImage);self.leftTopImage.layer.contentsRect =CGRectMake(0.0f,0.0f,0.5f,0.5f);self.rightTopImage.layer.contents = (__bridgeid_Nullable)(image.CGImage);self.rightTopImage.layer.contentsRect =CGRectMake(0.5f,0.0f,0.5f,0.5f);self.leftBottomImage.layer.contents = (__bridgeid_Nullable)(image.CGImage);self.leftBottomImage.layer.contentsRect =CGRectMake(0.0f,0.5f,0.5f,0.5f);}@end

運(yùn)行結(jié)果:

0EE9992A-027F-43C4-84DB-F2127EC2BCEE.png

拼合不僅給app提供了一個整潔的載入方式侠驯,還有效地提高了載入性能(單張大圖比多張小圖載入地更快)抡秆,但是如果有手動安排的話,他們還是有一些不方便的吟策,如果你需要在一個已經(jīng)創(chuàng)建好的品和圖上做一些尺寸上的修改或者其他變動儒士,無疑是比較麻煩的。

Mac上有一些商業(yè)軟件可以為你自動拼合圖片檩坚,這些工具自動生成一個包含拼合后的坐標(biāo)的XML或者plist文件着撩,拼合圖片的使用大大簡化。這個文件可以和圖片一同載入匾委,并給每個拼合的圖層設(shè)置contentsRect拖叙,這樣開發(fā)者就不用手動寫代碼來擺放位置了。

contentsCenter

CALayer的另一個屬性contentsCenter赂乐,有點(diǎn)類似于UIImage里的-resizableImageWithCapInsets: 方法薯鳍,樓主淺薄,實(shí)在不懂如何描述沪猴,這里有篇文章講得很清楚:iOS: 關(guān)于CALayer的contentsCenter屬性

3. CALayer位置坐標(biāo)相關(guān)的屬性

對應(yīng)于UIView的frame辐啄、bounds、center运嗜,CALayer有frame、bounds悯舟、position担租,訪問UIView的這三個屬性,返回的其實(shí)就是CALayer對應(yīng)的這三個值抵怎。但是CALayer另外還有一個比較難于理解的屬性anchorPoint奋救。

anchorPoint

anchorPoint決定了CALayer的那個點(diǎn)處于position的位置,其作用效果如下圖:

3.3.jpeg

坐標(biāo)轉(zhuǎn)換

CALayer也有用于在不同坐標(biāo)系中轉(zhuǎn)換坐標(biāo)的函數(shù):

-(CGPoint)convertPoint:(CGPoint)p fromLayer:(nullableCALayer*)l;-(CGPoint)convertPoint:(CGPoint)p toLayer:(nullableCALayer*)l;-(CGRect)convertRect:(CGRect)r fromLayer:(nullableCALayer*)l;-(CGRect)convertRect:(CGRect)r toLayer:(nullableCALayer*)l;

zPosition

CALayer的zPosition屬性可以控制圖層的顯示順序反惕,Interface Build布局如下:

Paste_Image.png

修改zPosition:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*blueView;@property(weak,nonatomic)IBOutletUIView*orangeView;@end@implementationViewController-(void)viewDidLoad {? [superviewDidLoad];self.blueView.layer.zPosition =1.0f;}@end

運(yùn)行結(jié)果:

Paste_Image.png

zPosition屬性雖然可以改變圖層的顯示順序尝艘,但是不能改變圖層在圖層樹中的順序

CALayer事件處理

CALayer并不關(guān)心任何響應(yīng)鏈?zhǔn)录圆荒苤苯犹幚碛|摸事件或者手勢姿染。但是它有一系列的方法幫你處理事件:-containsPoint:和-hitTest:背亥。

-containsPoint:接受一個在本圖層坐標(biāo)系下的CGPoint,如果這個點(diǎn)在圖層frame范圍內(nèi)就返回YES。舉個栗子:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*whiteView;@property(weak,nonatomic)IBOutletUIView*orangeView;@end@implementationViewController-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{UITouch*touch = touches.anyObject;CGPointoriginPoint = [touch locationInView:self.view];CGPointthePoint = [self.whiteView.layer convertPoint:originPoint fromLayer:self.view.layer];BOOLcontainsResult = [self.whiteView.layer containsPoint:thePoint];if(containsResult) {? ? ? thePoint = [self.orangeView.layer convertPoint:thePoint fromLayer:self.whiteView.layer];? ? ? containsResult = [self.orangeView.layer containsPoint:thePoint];UIAlertController*alert;if(containsResult) {? ? ? ? ? alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside orange layer"preferredStyle:UIAlertControllerStyleAlert];? ? ? }else{? ? ? ? ? alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside white layer"preferredStyle:UIAlertControllerStyleAlert];? ? ? }? ? ? [alert addAction:[UIAlertActionactionWithTitle:@"OK"style:UIAlertActionStyleCancelhandler:nil]];? ? ? [selfpresentViewController:alert animated:YEScompletion:nil];? }}@end

運(yùn)行結(jié)果:

Paste.gif

-hitTest:方法同樣接受一個CGPoint類型參數(shù)狡汉,而不是BOOL類型娄徊,它返回圖層本身,或者包含這個坐標(biāo)點(diǎn)的葉子節(jié)點(diǎn)圖層盾戴,如果這個點(diǎn)在最外面圖層的范圍之外寄锐,則返回nil。

下面這段代碼實(shí)現(xiàn)了上圖一樣的效果:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{UITouch*touch = touches.anyObject;CGPointoriginPoint = [touch locationInView:self.view];CALayer*layer = [self.whiteView.layer hitTest:originPoint];UIAlertController*alert;if(layer ==self.orangeView.layer) {? ? ? alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside orange layer"preferredStyle:UIAlertControllerStyleAlert];? }else{? ? ? alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside white layer"preferredStyle:UIAlertControllerStyleAlert];? }? [alert addAction:[UIAlertActionactionWithTitle:@"OK"style:UIAlertActionStyleCancelhandler:nil]];? [selfpresentViewController:alert animated:YEScompletion:nil];}

4. CALayer視覺相關(guān)的屬性

conrnerRadius

CALayer有一個叫做conrnerRadius的屬性控制著圖層角的曲率尖啡。它是一個浮點(diǎn)數(shù)橄仆,默認(rèn)為0(為0的時候就是直角),但是你可以把它設(shè)置成任意值衅斩。默認(rèn)情況下沿癞,這個曲率值只影響背景顏色而不影響背景圖片或是子圖層。不過矛渴,如果把masksToBounds設(shè)置成YES的話椎扬,圖層里面的所有東西都會被截取。

Interface Build布局如下:

Paste_Image.png

添加如下代碼:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*topWhiteView;@property(weak,nonatomic)IBOutletUIView*bottomWhiteView;@end@implementationViewController-(void)viewDidLoad {? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.topWhiteView.layer.cornerRadius =20.0f;self.bottomWhiteView.layer.cornerRadius =20.0f;self.bottomWhiteView.layer.masksToBounds =YES;}@end

運(yùn)行效果:

Paste_Image.png

borderWidth和borderColor

CALayer另外兩個非常有用屬性就是borderWidth和borderColor具温。二者共同定義了圖層邊的繪制樣式蚕涤。這條線(也被稱作stroke)沿著圖層的bounds繪制,同時也包含圖層的角铣猩。在上面代碼的基礎(chǔ)上再加上幾句:

self.topWhiteView.layer.borderWidth=5.0f;self.bottomWhiteView.layer.borderWidth=5.0f;self.topWhiteView.layer.borderColor= [UIColor yellowColor].CGColor;self.bottomWhiteView.layer.borderColor= [UIColor yellowColor].CGColor;

運(yùn)行效果:

Paste_Image.png

陰影效果

CALayer還有一系列屬性用來繪制陰影:

/** Shadow properties. **//* The color of the shadow. Defaults to opaque black. Colors created

* from patterns are currently NOT supported. Animatable. */@property(nullable) CGColorRef shadowColor;/* The opacity of the shadow. Defaults to 0. Specifying a value outside the

* [0,1] range will give undefined results. Animatable. */@propertyfloat shadowOpacity;/* The shadow offset. Defaults to (0, -3). Animatable. */@propertyCGSize shadowOffset;/* The blur radius used to create the shadow. Defaults to 3. Animatable. */@propertyCGFloat shadowRadius;/* When non-null this path defines the outline used to construct the

* layer's shadow instead of using the layer's composited alpha

* channel. The path is rendered using the non-zero winding rule.

* Specifying the path explicitly using this property will usually

* improve rendering performance, as will sharing the same path

* reference across multiple layers. Upon assignment the path is copied.

* Defaults to null. Animatable. */@property(nullable) CGPathRef shadowPath;

在前面代碼的基礎(chǔ)上再加上幾句:

self.topWhiteView.layer.shadowColor= [UIColorblackColor].CGColor;self.bottomWhiteView.layer.shadowColor= [UIColorblackColor].CGColor;self.topWhiteView.layer.shadowOpacity=0.5f;self.bottomWhiteView.layer.shadowOpacity=0.5f;

運(yùn)行效果:

Paste_Image.png

發(fā)現(xiàn)兩個問題:

1揖铜、topWhiteView有陰影,但是陰影在視圖的上方

2达皿、而bottomWhiteView干脆根本沒有陰影

第一個問題的原因在于這個屬性:

/* The shadowoffset. Defaultsto(0,-3). Animatable. */@propertyCGSize shadowOffset;

CALayer的陰影偏移量默認(rèn)為(0, -3)天吓,所以陰影出現(xiàn)在了視圖的上方

第二個問題的原因在于這句代碼:

self.bottomWhiteView.layer.masksToBounds= YES;

如果你開啟了masksToBounds屬性,所有從圖層中突出來的內(nèi)容都會被才剪掉峦椰,一個簡單的解決辦法就是在bottomWhiteView的下面再插入一個view來充當(dāng)陰影視圖龄寞。

修改之前的代碼,最終代碼如下:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*topWhiteView;@property(weak,nonatomic)IBOutletUIView*bottomWhiteView;@property(weak,nonatomic)IBOutletUIView*bottomBackView;@end@implementationViewController-(void)viewDidLoad {? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.bottomWhiteView.layer.masksToBounds =YES;? [selfconfigLayer:self.topWhiteView.layer];? [selfconfigLayer:self.bottomWhiteView.layer];? [selfconfigLayer:self.bottomBackView.layer];}-(void)configLayer:(CALayer*)aLayer{? aLayer.cornerRadius =20.0f;//圓角aLayer.borderWidth =5.0f;//邊框線寬aLayer.borderColor = [UIColoryellowColor].CGColor;//邊框顏色aLayer.shadowColor = [UIColorblackColor].CGColor;//陰影顏色aLayer.shadowOpacity =0.5f;//陰影透明度aLayer.shadowOffset =CGSizeMake(5.0f,5.0f);//陰影偏移量}@end

運(yùn)行效果:

Paste_Image.png

shadowRadius

shadowRadius屬性可以控制CALayer陰影的模糊度汤功,在viewDidLoad方法的最后加上一句:

self.topWhiteView.layer.shadowRadius=10.0f;

運(yùn)行結(jié)果:

Paste_Image.png

shadowPath

shadowPath可以為CALayer指定特定的陰影路徑物邑。

舉個栗子:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*orangeView;@property(weak,nonatomic)IBOutletUIView*cyanView;@end@implementationViewController-(void)viewDidLoad {? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.[selfconfigLayer:self.orangeView.layer];? [selfconfigLayer:self.cyanView.layer];//create a square shadowCGMutablePathRefsquarePath =CGPathCreateMutable();CGPathAddRect(squarePath,NULL,self.cyanView.bounds);self.cyanView.layer.shadowPath = squarePath;CGPathRelease(squarePath);//create a circular shadowCGMutablePathRefcirclePath =CGPathCreateMutable();CGPathAddEllipseInRect(circlePath,NULL,self.orangeView.bounds);self.orangeView.layer.shadowPath = circlePath;CGPathRelease(circlePath);}-(void)configLayer:(CALayer*)aLayer{? aLayer.shadowOpacity =0.5f;? aLayer.cornerRadius = aLayer.bounds.size.width /2.0f;? aLayer.shadowOffset =CGSizeMake(0.0f,0.0f);? aLayer.shadowRadius =5.0f;}@end

運(yùn)行效果:

Paste_Image.png

mask

mask圖層定義了父圖層的部分可見區(qū)域,mask圖層的Color屬性是無關(guān)緊要的滔金,真正重要的是圖層的輪廓色解。mask屬性就像是一個餅干切割機(jī),mask圖層實(shí)心的部分會被保留下來餐茵,其他的則會被拋棄科阎。

舉個栗子:

Interface Build布局如下:

Paste_Image.png

使用下面這個小雪人來充當(dāng)圖層蒙版:

3.png

代碼如下:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIImageView*imageView;@end@implementationViewController-(void)viewDidLoad {? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.//create mask layerCALayer*maskLayer = [CALayerlayer];? maskLayer.frame =self.imageView.bounds;UIImage*maskImage = [UIImageimageNamed:@"3"];? maskLayer.contents = (__bridgeid)maskImage.CGImage;? maskLayer.contentsGravity = kCAGravityCenter;? maskLayer.contentsScale = [UIScreenmainScreen].scale;//apply mask to image layerself.imageView.layer.mask = maskLayer;}@end

運(yùn)行效果:

Paste_Image.png


每一個UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個CALayer,我們可用稱這個Layer為Root Layer(根層)

所有的非Root Layer忿族,也就是手動創(chuàng)建的CALayer對象锣笨,都存在著隱式動畫

什么是隱式動畫蝌矛?

當(dāng)對非Root Layer的部分屬性進(jìn)行修改時,默認(rèn)會自動產(chǎn)生一些動畫效果

而這些屬性稱為Animatable Properties(可動畫屬性)

列舉幾個常見的Animatable Properties:

bounds:用于設(shè)置CALayer的寬度和高度票唆。修改這個屬性會產(chǎn)生縮放動畫

backgroundColor:用于設(shè)置CALayer的背景色朴读。修改這個屬性會產(chǎn)生背景色的漸變動畫

position:用于設(shè)置CALayer的位置。修改這個屬性會產(chǎn)生平移動畫

......


1.UIView可以通過subviews屬性訪問所有的子視圖走趋,類似地衅金,CALayer也可以通過sublayers屬性訪問所有的子層

2.UIView可以通過superview屬性訪問父視圖,類似地簿煌,CALayer也可以通過superlayer屬性訪問父層

3.特別注意:如果一個控件是另外一個控件的子控件氮唯,那么這個控件的layer也是另一個控件的子layer。

查看蘋果的官方文檔姨伟,下面的屬性都可以通過KVC進(jìn)行設(shè)置惩琉。

//

//? YYMylayer.m

//? 05-自定義layer(1)

//

//? Created by apple on 14-6-21.

//? Copyright (c) 2014年 itcase. All rights reserved.

//

#import "YYMylayer.h"

@implementation YYMylayer

//重寫該方法,在該方法內(nèi)繪制圖形

-(void)drawInContext:(CGContextRef)ctx

{

//1.繪制圖形

//畫一個圓

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

//設(shè)置屬性(顏色)

//? ? [[UIColor yellowColor]set];

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

//2.渲染

CGContextFillPath(ctx);

}

@en




//

//? YYViewController.m

//? 05-自定義layer(1)

//

//? Created by apple on 14-6-21.

//? Copyright (c) 2014年 itcase. All rights reserved.

//

#import "YYViewController.h"

#import "YYMylayer.h"

@interface YYViewController ()

@end

@implementation YYViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//1.創(chuàng)建自定義的layer

YYMylayer *layer=[YYMylayer layer];

//2.設(shè)置layer的屬性

layer.backgroundColor=[UIColor brownColor].CGColor;

layer.bounds=CGRectMake(0, 0, 200, 150);

layer.anchorPoint=CGPointZero;

layer.position=CGPointMake(100, 100);

layer.cornerRadius=20;

layer.shadowColor=[UIColor blackColor].CGColor;

layer.shadowOffset=CGSizeMake(10, 20);

layer.shadowOpacity=0.6;

[layer setNeedsDisplay];

//3.添加layer

[self.view.layer addSublayer:layer];

}

@end



注意點(diǎn):

(1)默認(rèn)為無色夺荒,不會顯示瞒渠。要想讓繪制的圖形顯示出來,還需要設(shè)置圖形的顏色技扼。注意不能直接使用UI框架中的類

(2)在自定義layer中的-(void)drawInContext:方法不會自己調(diào)用伍玖,只能自己通過setNeedDisplay方法調(diào)用,在view中畫東西DrawRect:方法在view第一次顯示的時候會自動調(diào)用剿吻。

實(shí)現(xiàn)效果:





#import "YYVIEW.h"

@implementation YYVIEW

- (void)drawRect:(CGRect)rect

{

//1.獲取上下文

CGContextRef ctx=UIGraphicsGetCurrentContext();

//2.繪制圖形

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

//設(shè)置屬性(顏色)

//? ? [[UIColor yellowColor]set];

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

//3.渲染

CGContextFillPath(ctx);

//在執(zhí)行渲染操作的時候窍箍,本質(zhì)上它的內(nèi)部相當(dāng)于調(diào)用了下面的方法

[self.layer drawInContext:ctx];

}


說明:在UIView中繪制圖形,獲取的上下文就是這個view對應(yīng)的layer的上下文丽旅。在渲染的時候椰棘,就是把圖形渲染到對應(yīng)的layer上。

在執(zhí)行渲染操作的時候榄笙,本質(zhì)上它的內(nèi)部相當(dāng)于執(zhí)行了?[self.layer drawInContext:ctx];


二邪狞、第二種方式

方法描述:設(shè)置CALayer的delegate,然后讓delegate實(shí)現(xiàn)drawLayer:inContext:方法办斑,當(dāng)CALayer需要繪圖時外恕,會調(diào)用delegate的drawLayer:inContext:方法進(jìn)行繪圖。

代碼示例:

//

//? YYViewController.m

//? 06-自定義layer(2)

//

//? Created by apple on 14-6-21.

//? Copyright (c) 2014年 itcase. All rights reserved.

#import "YYViewController.h"

@interface YYViewController ()

@end

@implementation YYViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//1.創(chuàng)建自定義的layer

CALayer *layer=[CALayer layer];

//2.設(shè)置layer的屬性

layer.backgroundColor=[UIColor brownColor].CGColor;

layer.bounds=CGRectMake(0, 0, 200, 150);

layer.anchorPoint=CGPointZero;

layer.position=CGPointMake(100, 100);

layer.cornerRadius=20;

layer.shadowColor=[UIColor blackColor].CGColor;

layer.shadowOffset=CGSizeMake(10, 20);

layer.shadowOpacity=0.6;

//設(shè)置代理

layer.delegate=self;

[layer setNeedsDisplay];

//3.添加layer

[self.view.layer addSublayer:layer];

}

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

{

//1.繪制圖形

//畫一個圓

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

//設(shè)置屬性(顏色)

//? ? [[UIColor yellowColor]set];

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

//2.渲染

CGContextFillPath(ctx);

}

@end



注意點(diǎn):不能再將某個UIView設(shè)置為CALayer的delegate乡翅,因?yàn)閁IView對象已經(jīng)是它內(nèi)部根層的delegate,再次設(shè)置為其他層的delegate就會出問題罪郊。

在設(shè)置代理的時候蠕蚜,它并不要求我們遵守協(xié)議,說明這個方法是nsobject中的悔橄,就不需要再額外的顯示遵守協(xié)議了靶累。

提示:以后如果要設(shè)置某個類的代理腺毫,但是這個代理沒要求我們遵守什么特定的協(xié)議,那么可以認(rèn)為這個協(xié)議方法是NSObject里邊的挣柬。

三潮酒、補(bǔ)充說明

(1)無論采取哪種方法來自定義層,都必須調(diào)用CALayer的setNeedsDisplay方法才能正常繪圖邪蛔。

(2)詳細(xì)現(xiàn)實(shí)過程:

當(dāng)UIView需要顯示時急黎,它內(nèi)部的層會準(zhǔn)備好一個CGContextRef(圖形上下文),然后調(diào)用delegate(這里就是UIView)的drawLayer:inContext:方法侧到,并且傳入已經(jīng)準(zhǔn)備好的CGContextRef對象勃教。而UIView在drawLayer:inContext:方法中又會調(diào)用自己的drawRect:方法。平時在drawRect:中通過UIGraphicsGetCurrentContext()獲取的就是由層傳入的CGContextRef對象匠抗,在drawRect:中完成的所有繪圖都會填入層的CGContextRef中故源,然后被拷貝至屏幕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汞贸,一起剝皮案震驚了整個濱河市绳军,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矢腻,老刑警劉巖门驾,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異踏堡,居然都是意外死亡猎唁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門顷蟆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诫隅,“玉大人,你說我怎么就攤上這事帐偎≈鹞常” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵削樊,是天一觀的道長豁生。 經(jīng)常有香客問我,道長漫贞,這世上最難降的妖魔是什么甸箱? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮迅脐,結(jié)果婚禮上芍殖,老公的妹妹穿的比我還像新娘。我一直安慰自己谴蔑,他們只是感情好豌骏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布龟梦。 她就那樣靜靜地躺著,像睡著了一般窃躲。 火紅的嫁衣襯著肌膚如雪计贰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天蒂窒,我揣著相機(jī)與錄音躁倒,去河邊找鬼。 笑死刘绣,一個胖子當(dāng)著我的面吹牛樱溉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纬凤,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼福贞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了停士?” 一聲冷哼從身側(cè)響起挖帘,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恋技,沒想到半個月后拇舀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜻底,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年骄崩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薄辅。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡扔字,死狀恐怖鲫咽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情九默,我是刑警寧澤博其,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布浴麻,位于F島的核電站螃概,受9級特大地震影響政勃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旧乞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一蔚润、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尺栖,春花似錦抽碌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至皮胡,卻和暖如春痴颊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屡贺。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工蠢棱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甩栈。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓泻仙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親量没。 傳聞我的和親對象是個殘疾皇子玉转,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容