IOS開發-CALayer和UIView詳細匯總


1.    CALayer和UIView之間的關系:

  •  在iOS系統中,你能看得見摸得着的東西基本上都是UIView,比如UI控件、圖標等等,都是UIView。
  •  其實UIView之所以能顯示在屏幕上,完全是因為它內部的一個層(CALayer)。
  •  在創建UIView對象時,UIView內部會自動創建一個層(即CALayer對象),通過UIView的layer屬性可以訪問這個層。當UIView需要顯示到屏幕上時,會調用drawRect:方法進行繪圖,並且會將所有內容繪制在自己的層上,繪圖完畢后,系統會將層拷貝到屏幕上,於是就完成了UIView的顯示。
  •  換句話說,UIView本身不具備顯示的功能,是它內部的層才有顯示功能。
  • UIView之所以能夠顯示,完全是因為內部的CALayer對象。因此,通過操作這個CALayer對象,可以很方便地調整UIView的一些界面屬性,比如:陰影、圓角大小、邊框寬度和顏色等。

設置圖片的圓角和旋轉:

1 UIImageView *im = [[UIImageView alloc]init]; 2     im.frame = CGRectMake(100, 100, 100, 100); 3     im.image = [UIImage imageNamed:@"收藏背景"]; 4     im.layer.cornerRadius = 10; 5     im.layer.masksToBounds = YES; 6     im.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1); 7     [self.view addSubview:im];

2.UIView可以通過addSubview:方法添加子視圖,類似地,CALayer可以通過addSublayer:方法添加子層

 1   CALayer *myLayer = [CALayer layer];  2  // 設置層的寬度和高度(100x100)
 3  myLayer.bounds = CGRectMake(0, 0, 100, 100);  4   // 設置層的位置
 5   myLayer.position = CGPointMake(200, 100);  6   // 設置需要顯示的圖片
 7   myLayer.contents = (id)[UIImage imageNamed:@"0000.png"].CGImage;  8   // 設置層的圓角半徑為10
 9   myLayer.cornerRadius = 10; 10  // 如果設置了圖片,需要設置這個屬性為YES才有圓角效果
11   myLayer.masksToBounds = YES; 12  
13  // 添加myLayer到控制器的view的layer中
14  [self.view.layer addSublayer:myLayer];
補充:CGImage是一種CGImageRef類型的數據
比如處理圖片只顯示某部分的時候,就用到了CGImageRef
 1    UIImage *ima = [UIImage imageNamed:@"收藏背景"];  2 // 圖片中需要顯示的部分
 3     CGRect rect = CGRectMake(50, 50, 70, 70);  4 // 獲得顯示部分的數據
 5     CGImageRef imageref = CGImageCreateWithImageInRect([ima CGImage], rect);  6 // 將數據轉化為圖片
 7     UIImage *subimage = [UIImage imageWithCGImage:imageref];  8     UIImageView *imageview = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];  9     imageview.image = subimage; 10     [self.view addSubview:imageview];

3.為什么CALayer中使用CGColorRef和CGImageRef這2種數據類型,而不用UIColor和UIImage?

* 首先要知道:CALayer是定義在QuartzCore框架中的;CGImageRef、CGColorRef兩種數據類型是定義在CoreGraphics框架中的;UIColor、UIImage是定義在UIKit框架中的

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

* 因此,為了保證可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef

* 不過很多情況下,可以通過UIKit對象的特定方法,得到CoreGraphics對象,比如UIImage的CGImage方法可以返回一個CGImageRef

 

4.如何選擇UIView和CALayer?

    UIView相對於CALayer來說就是多一個事件處理的功能,CALayer是不能處理用戶的觸摸事件。故如果顯示出來的東西需要跟用戶進行交互的話,用UIView;如果不需要跟用戶進行交互,用UIView或者CALayer都可以。

 

5.其實UIView的顯示過程

        當UIView需要顯示時,它內部的層會准備好一個CGContextRef(圖形上下文),然后調用delegate(這里就是UIView)的drawLayer:inContext:方法,並且傳入已經准備好的CGContextRef對象。而UIView在drawLayer:inContext:方法中又會調用自己的drawRect:方法

        在drawRect:中通過UIGraphicsGetCurrentContext()獲取的就是由層傳入的CGContextRef對象,在drawRect:中完成的所有繪圖都會填入層的CGContextRef中,然后被拷貝至屏幕

 

6.自定義層

    a.新建一個繼承於CALayer的類AACALayer,然后覆蓋drawInContext:方法,在里面繪圖

   

 1 -(void)drawInContext:(CGContextRef)ctx{
 3     CGContextSetRGBFillColor(ctx, 0, 1, 0.5, 1);//填充,出現實心
 5 // 起點
 7     CGContextMoveToPoint(ctx, 50, 0);
 9 // 從(50, 0)連線到(0, 100)
11     CGContextAddLines(ctx, 0, 100);
13 // 從(0, 100)連線到(100, 100)
15     CGContextAddLineToPoint(ctx, 100, 100);
17 // 繪制路徑
19  CGContextClosePath(ctx); 20 
21  }

則每次創建AACALayer,都會繪制一個三角形 

1 AALayer *layer = [AALayer layer]; 2  // 設置層的寬高
3  layer.bounds = CGRectMake(0, 0, 100, 100); 4  // 設置層的位置
5  layer.position = CGPointMake(100, 100); 6  // 開始繪制圖層
7  [layer setNeedsDisplay];//寫這個方法才會自動觸發 drawInContext:的方法
8 [self.view.layer addSublayer:layer];

    b.不想寫子類,也可以直接使用代理可以新建層,drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx中繪圖,但是不能將UIView設置為它的代理,否則和UIView內部就沖突了,因為UIView已經是內部根圖層的degegate了。

 1  CALayer *layerr = [CALayer layer];  2   // 設置層的寬高
 3   layerr.bounds = CGRectMake(0, 0, 100, 100);  4   // 設置層的位置
 5   layerr.position = CGPointMake(100, 100);  6  laere.delegate - self;  7   // 開始繪制圖層
 8   [layer setNeedsDisplay];//無論采取哪種方法來自定義層,都必須調用CALayer的setNeedsDisplay方法才能正常繪圖。
 9  [self.view.layer addSublayer:layer]; 10 
11 //在代理方法中
12 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { 13      // 設置顏色
14      CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);//這不填充,空心 15      // 設置邊框寬度
16      CGContextSetLineWidth(ctx, 5); 17      
18      // 將矩形放到路徑中
19  CGContextAddRect(ctx, layer.bounds); 20      
21      // 繪制路徑
22  CGContextStrokePath(ctx); 23  } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM