国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

[iOSUI進階-6.0]CALayer

2019-11-14 19:38:48
字體:
供稿:網(wǎng)友
A.基本知識
1.需要掌握的
  • CALayer的基本屬性
  • CALayer和UIView的關系
  • position和anchorPoint的作用
 
2.概念
在iOS中,你能看得見摸得著的東西基本上都是UIView,比如一個按鈕、一個文本標簽、一個文本輸入框、一個圖標等等,這些都是UIView

其實UIView之所以能顯示在屏幕上,完全是因為它內(nèi)部的一個圖層

在創(chuàng)建UIView對象時,UIView內(nèi)部會自動創(chuàng)建一個圖層(即CALayer對象),通過UIView的layer屬性可以訪問這個層
@PRoperty(nonatomic,readonly,retain) CALayer *layer;

當UIView需要顯示到屏幕上時,會調(diào)用drawRect:方法進行繪圖,并且會將所有內(nèi)容繪制在自己的圖層上,繪圖完畢后,系統(tǒng)會將圖層拷貝到屏幕上,于是就完成了UIView的顯示

換句話說,UIView本身不具備顯示的功能,是它內(nèi)部的層才有顯示功能
 
3.基本使用
通過操作CALayer對象,可以很方便地調(diào)整UIView的一些外觀屬性,比如:
陰影
圓角大小
邊框?qū)挾群皖伾?br />… …

還可以給圖層添加動畫,來實現(xiàn)一些比較炫酷的效果
 
4.屬性
(1)基本屬性
邊框顏色(CGColorRef類型)
@property CGColorRef borderColor;

邊框?qū)挾?br />@property CGFloat borderWidth;

圓角半徑
@property CGColorRef borderColor;

內(nèi)容(比如設置為圖片CGImageRef)
@property(retain) id contents;
 
(2)transform3d key paths
Image(14)
 
  1 //  2 //  ViewController.m  3 //  CALayerTest  4 //  5 //  Created by hellovoidworld on 15/1/14.  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.  7 //  8   9 #import "ViewController.h" 10  11 @interface ViewController () 12 @property (weak, nonatomic) IBOutlet UIView *orangeView; 13  14 @end 15  16 @implementation ViewController 17  18 - (void)viewDidLoad { 19     [super viewDidLoad]; 20     // Do any additional setup after loading the view, typically from a nib. 21     22 //    [self testBasicLayer]; 23     24 //    [self testOrangeView]; 25     26 //    [self testImageView]; 27     28     [self testTransform]; 29 } 30  31 /** 基本屬性 */ 32 - (void) testBasicLayer { 33     //  創(chuàng)建一個圖層 34     CALayer *layer = [[CALayer alloc] init]; 35     // 設置圖層邊框顏色 36     layer.borderColor = [UIColor blueColor].CGColor; 37     //  設置圖層邊框粗細,邊框是占據(jù)view內(nèi)的尺寸的 38     layer.borderWidth = 10; 39     // 40     layer.frame = CGRectMake(50, 100, 200, 200); 41     layer.backgroundColor = [UIColor redColor].CGColor; 42     layer.cornerRadius = 15; 43     //    layer.masksToBounds = YES; 44     45     46     //    UIImage *image = [UIImage imageNamed:@"M3Mini"]; 47     //    layer.contents = (id)image.CGImage; 48     49     layer.shadowColor = [UIColor blackColor].CGColor; 50     layer.shadowOffset = CGSizeMake(50, 50); 51     layer.shadowOpacity = 0.5; 52     53     [self.view.layer addSublayer:layer]; 54 } 55  56 /** UIView的圓角+陰影 */ 57 - (void) testOrangeView { 58     self.orangeView.layer.shadowColor = [UIColor blackColor].CGColor; 59     self.orangeView.layer.shadowOffset = CGSizeMake(20, 20); 60     self.orangeView.layer.shadowOpacity = 0.5; 61     self.orangeView.layer.cornerRadius = 15; 62     63     self.orangeView.layer.borderWidth = 10; 64 } 65  66 /** ImageView的圓角+陰影效果 */ 67 - (void) testImageView { 68     // 用于產(chǎn)生陰影的輔助view,作為父view,顯示在底層 69     UIView *shadowView = [[UIView alloc] init]; 70     shadowView.frame = CGRectMake(50, 80, 100, 64); 71     shadowView.layer.cornerRadius = 10; 72     shadowView.backgroundColor = [UIColor redColor]; 73     74     // 產(chǎn)生陰影 75     shadowView.layer.shadowColor = [UIColor blueColor].CGColor; 76     shadowView.layer.shadowOffset = CGSizeMake(10, 10); 77     shadowView.layer.shadowOpacity = 0.7; 78     79     // 用于顯示圓角內(nèi)容的imageView,作為子view,顯示在表層 80     UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"M3Mini"]]; 81     imageView.frame = shadowView.bounds; 82     imageView.layer.cornerRadius = shadowView.layer.cornerRadius ; 83     84     // 圓角裁剪 85     imageView.layer.masksToBounds = YES; 86     87     // “合成”兩個view 88     [shadowView addSubview:imageView]; 89     90     // 添加到屏幕 91     [self.view addSubview:shadowView]; 92 } 93  94 /** 3D transform */ 95 - (void) testTransform { 96     UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"M3Mini"]]; 97     imageView.frame = CGRectMake(50, 80, 100, 64); 98     99     // 1.從3D的x、y、z軸三個向量的縮放100 //    imageView.layer.transform = CATransform3DMakeScale(2, 2, 0);101    102     // 2.沿著x=1,y=1,z=0的向量為軸旋轉(zhuǎn)103 //    imageView.layer.transform = CATransform3DMakeRotation(M_PI_4, 1, 1, 0);104    105     // 3.使用key paths設置106     // 3.1使用整個transform對象來設置,3D向量旋轉(zhuǎn)107 //    NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 1, 1, 0)];108 //    [imageView.layer setValue:value forKeyPath:@"transform"];109    110     // 3.2直接利用rotation來設置,2D旋轉(zhuǎn)(跟view的transform旋轉(zhuǎn)一樣)111     [imageView.layer setValue:@(M_PI_4) forKeyPath:@"transform.rotation"];112    113     [self.view addSubview:imageView];114 }115  116 - (void)didReceiveMemoryWarning {117     [super didReceiveMemoryWarning];118     // Dispose of any resources that can be recreated.119 }120 121 @end
 
 
#mark:
1.在同一個View上,使用了layer.masksToBounds=YES;的時候會屏蔽掉陰影效果;如果要同時使用。(注意,同時使用圓角和陰影是允許的)
例如: 要同時實現(xiàn)一個UIImageView的圓角和陰影效果,由于圖片所在圖層不是UIImageView的主layer,設置的圓角并不能影響到圖片(同時陰影也是沒有圓角的),所以必須要使用masksToBounds才能實現(xiàn)圓角。
 
單純同時使用圓角剪裁和陰影:
 1 - (void) testImageView { 2     UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"M3Mini"]]; 3     imageView.frame = CGRectMake(50, 80, 100, 64); 4     imageView.layer.cornerRadius = 10; 5     imageView.layer.masksToBounds = YES; 6     7     imageView.layer.shadowColor = [UIColor blueColor].CGColor; 8     imageView.layer.shadowOffset = CGSizeMake(10, 10); 9     imageView.layer.shadowOpacity = 0.7;10    11     [self.view addSubview:imageView];12 }
 
沒有陰影,因為被masksToBounds剪掉了:
Image(15)
 
解決:建議使用兩個view,用帶陰影的view(輔助view)和使用masksToBounds的view(需要顯示內(nèi)容的view)作為父子控件。
 1 - (void) testImageView { 2     // 用于產(chǎn)生陰影的輔助view,作為父view,顯示在底層 3     UIView *shadowView = [[UIView alloc] init]; 4     shadowView.frame = CGRectMake(50, 80, 100, 64); 5     shadowView.layer.cornerRadius = 10; 6     shadowView.backgroundColor = [UIColor redColor]; 7     8     // 產(chǎn)生陰影 9     shadowView.layer.shadowColor = [UIColor blueColor].CGColor;10     shadowView.layer.shadowOffset = CGSizeMake(10, 10);11     shadowView.layer.shadowOpacity = 0.7;12    13     // 用于顯示圓角內(nèi)容的imageView,作為子view,顯示在表層14     UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"M3Mini"]];15     imageView.frame = shadowView.bounds;16     imageView.layer.cornerRadius = shadowView.layer.cornerRadius ;17    18     // 圓角裁剪19     imageView.layer.masksToBounds = YES;20    21     // “合成”兩個view22     [shadowView addSubview:imageView];23    24     // 添加到屏幕25     [self.view addSubview:shadowView];26 }
 
Image(16)
 
 
5.關于CALayer的疑問
首先
CALayer是定義在QuartzCore框架中的
CGImageRef、CGColorRef兩種數(shù)據(jù)類型是定義在CoreGraphics框架中的
UIColor、UIImage是定義在UIKit框架中的

其次
QuartzCore框架和CoreGraphics框架是可以跨平臺使用的,在iOS和Mac OS X上都能使用
但是UIKit只能在iOS中使用

為了保證可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef
 
6.如何選擇UIView和CALayer
通過CALayer,就能做出跟UIImageView一樣的界面效果

既然CALayer和UIView都能實現(xiàn)相同的顯示效果,那究竟該選擇誰好呢?
其實,對比CALayer,UIView多了一個事件處理的功能。也就是說,CALayer不能處理用戶的觸摸事件,而UIView可以
所以,如果顯示出來的東西需要跟用戶進行交互的話,用UIView;如果不需要跟用戶進行交互,用UIView或者CALayer都可以
當然,CALayer的性能會高一些,因為它少了事件處理的功能,更加輕量級
 
7. position & anchorPoint
CALayer有2個非常重要的屬性:position和anchorPoint

@property CGPoint position;
用來設置CALayer在父層中的位置
以父層的左上角為原點(0, 0)

@property CGPoint anchorPoint;
稱為“定位點”、“錨點”
決定著CALayer身上的哪個點會在position屬性所指的位置
以自己的左上角為原點(0, 0)
它的x、y取值范圍都是0~1,默認值為(0.5, 0.5)
 
1     CALayer *layer = [[CALayer alloc] init];2     layer.backgroundColor = [UIColor redColor].CGColor;3     layer.frame = CGRectMake(0, 0, 100, 100);4     layer.position = CGPointMake(50, 50);5     // anchorPoint默認是(0.5,0.5),即中心點6     layer.anchorPoint = CGPointMake(0,0);7   8     [self.view.layer addSublayer:layer];
 
Image(17)
 
8.隱式動畫
每一個UIView內(nèi)部都默認關聯(lián)著一個CALayer,我們可用稱這個Layer為Root Layer(根層)

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

什么是隱式動畫?
當對非Root Layer的部分屬性進行修改時,默認會自動產(chǎn)生一些動畫效果
而這些屬性稱為Animatable Properties(可動畫屬性)

列舉幾個常見的Animatable Properties:
bounds:用于設置CALayer的寬度和高度。修改這個屬性會產(chǎn)生縮放動畫
backgroundColor:用于設置CALayer的背景色。修改這個屬性會產(chǎn)生背景色的漸變動畫
position:用于設置CALayer的位置。修改這個屬性會產(chǎn)生平移動畫
 
可以通過動畫事務(CATransaction)關閉默認的隱式動畫效果
1 [CATransaction begin];2 [CATransaction setDisableActions:YES];3 self.myview.layer.position = CGPointMake(10, 10);4 [CATransaction commit];
 
1 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {2     // 縮放3     self.layer.frame = CGRectMake(self.layer.position.x, self.layer.position.y, 200, 200);4     // 位移5     self.layer.position = CGPointMake(200, 200);6     // 背景色7     self.layer.backgroundColor = [UIColor blueColor].CGColor;8 }
 
Image(18)
 
10.自定義圖層
有兩種方法:自己創(chuàng)建layer類和使用代理
(1)創(chuàng)建繼承CALayer的類,并實現(xiàn)drawInContent:方法來繪畫
 1 // 2 //  HVWLayer.m 3 //  CALayerTest 4 // 5 //  Created by hellovoidworld on 15/1/14. 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved. 7 // 8  9 #import "HVWLayer.h"10 11 @implementation HVWLayer12 13 14 /**15 * 必須調(diào)用一次layer的setNeedDisplay方法,才能觸發(fā)此方法16 */17 - (void)drawInContext:(CGContextRef)ctx {18     NSLog(@"%@ - drawInContext", [self class]);19    20     // 綠色21     CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);22     // 矩形23     CGContextFillRect(ctx, CGRectMake(50, 50, 100, 100));24     CGContextFillPath(ctx);25 }26 27 @end
 
viewController:
1 - (void) diyLayer1 {2     HVWLayer *layer = [[HVWLayer alloc] init];3     layer.frame = CGRectMake(80, 80, 200, 300);4     layer.backgroundColor = [UIColor grayColor].CGColor;5     // 必須調(diào)用重繪,才能觸發(fā)layer的drawInContent:方法6     [layer setNeedsDisplay];7    8     [self.view.layer addSublayer:layer];9 }
 
Image(19)
 
(2)使用layer的delegate
viewController:
 1 - (void) diyLayer2 { 2     CALayer *layer = [[CALayer alloc] init]; 3     layer.bounds = CGRectMake(0, 0, 200, 300); 4     layer.anchorPoint = CGPointZero; 5     layer.backgroundColor = [UIColor grayColor].CGColor; 6     layer.delegate = self; 7     8     // 必須要進行重繪 9     [layer setNeedsDisplay];10    11     [self.view.layer addSublayer:layer];12 }13  14 #pragma mark - layer代理方法15 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {16     // 綠色17     CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);18     // 矩形19     CGContextFillRect(ctx, CGRectMake(30, 30, 100, 100));20     CGContextFillPath(ctx);21 }

 

Image(20)
 
 
11.View和layer的調(diào)用關系
(1)view的layer加載順序
  • view準備一個圖層上下文Layer Context Ref
  • 調(diào)用[view.layer.delegate drawLayer:inContext:],傳入上下文
  • 在drawLayer:inContext:內(nèi)會調(diào)用view的drawRect:方法
  • 所以drawRect:內(nèi)實現(xiàn)的繪圖方法,會畫到layer上
  • 系統(tǒng)把layer上的內(nèi)容描繪到屏幕,完成view的顯示
 
view: (創(chuàng)建了一個紅圓)
 1 // 2 //  HVWView.m 3 //  CALayerTest 4 // 5 //  Created by hellovoidworld on 15/1/14. 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved. 7 // 8  9 #import "HVWView.h"10 11 @implementation HVWView12 13 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {14     NSLog(@"%@ - drawLayer", [self class]);15     [super drawLayer:layer inContext:ctx];16 }17 18 - (void)drawRect:(CGRect)rect {19     NSLog(@"%@ - drawRect", [self class]);20     CGContextRef ctx = UIGraphicsGetCurrentContext();21     CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);22     CGContextFillEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));23     CGContextFillPath(ctx);24 }25 26 @end
 
layer:(創(chuàng)建一個綠矩形)
 1 // 2 //  HVWLayer.m 3 //  CALayerTest 4 // 5 //  Created by hellovoidworld on 15/1/14. 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved. 7 // 8  9 #import "HVWLayer.h"10 11 @implementation HVWLayer12 13 14 - (void)drawInContext:(CGContextRef)ctx {15     NSLog(@"%@ - drawInContext", [self class]);16    17     // 綠色18     CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);19     // 矩形20     CGContextFillRect(ctx, CGRectMake(100, 100, 100, 100));21     CGContextFillPath(ctx);22 }23  24 @end
 
ViewController:
 1 - (void)viewDidLoad { 2     [super viewDidLoad]; 3     // Do any additional setup after loading the view, typically from a nib. 4     5     // 創(chuàng)建view 6     HVWView *hvwView = [[HVWView alloc] init]; 7     hvwView.backgroundColor = [UIColor grayColor]; 8     hvwView.frame = CGRectMake(50, 50, 250, 250); 9    10     // 創(chuàng)建layer11     HVWLayer *layer = [[HVWLayer alloc] init];12     layer.frame = CGRectMake(50, 50, 250, 250);13     layer.backgroundColor = [UIColor blueColor].CGColor;14    15     // 必須要重繪才能調(diào)用layer的drawInContext16     [layer setNeedsDisplay];17    18     // 配置layer到view,會設置layer的delegate就是那個view19     [hvwView.layer addSublayer:layer];20    21     [self.view addSubview:hvwView];22 //    [self.view.layer addSublayer:layer];23 }
 
Image(21)
 
consol:
2015-01-14 21:59:45.558 CALayerTest3[3246:115305] HVWView - drawLayer
2015-01-14 21:59:45.560 CALayerTest3[3246:115305] HVWView - drawRect
2015-01-14 21:59:45.561 CALayerTest3[3246:115305] HVWLayer - drawInContext
 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 万安县| 西宁市| 射洪县| 光泽县| 隆德县| 扎囊县| 云安县| 贵溪市| 万山特区| 绥滨县| 微山县| 宁明县| 黄龙县| 皋兰县| 绥宁县| 腾冲县| 彭州市| 大余县| 岑巩县| 虹口区| 涡阳县| 武胜县| 石屏县| 金寨县| 万盛区| 扎囊县| 汽车| 南宫市| 盘山县| 宝丰县| 西峡县| 濮阳市| 建始县| 崇义县| 巴马| 庐江县| 湘乡市| 鹤庆县| 于田县| 德昌县| 鹤庆县|