IOS SDK詳解之CALayer(一),iossdk詳解calayer
原創Blog,轉載請註明出處
http://blog.csdn.net/hello_hwc?viewmode=contents
前言:這個系列要更新Core Animation的內容,但是CALayer是Core Animation的基礎。
一 CALayer是什嗎?
摘自官網的一句話-Layers Provide the Basis for Drawing and Animations(Layers是繪圖和動畫的基礎)
Layer是在3D空間中的2D平面。Layer管理的幾何(例如rotate,transfrom),內容(image等),和可視屬性(backgroundColor,alpha)等資訊。Layer主要通過管理bitmap來維護自己的狀態資訊,從這一點上來說,Layer可以看作物件模型,因為他們主要用來管理資料。
Layer是基於bitmap的,它會捕獲View要呈現的內容,然後cache在一個bitmap中,這個bitmap可以看作一個對象。這樣每次進行操作,例如平移旋轉等,只是bitmap的矩陣運算。基於Layer的動畫過程
由於基於Layer的繪製是處理靜態Bitmap的,而bitmap的處理又是GPU所擅長的,所以它的效率要比基於View繪製的高很多,因為基於View繪製的每次都要進行drawRect的調用重新繪製。
二 Layer支援繼承,支援添加Sublayer,支援對sublayer進行層次調整
常用的Layer子類
CAEmitterLayer |
發射器層,用來控制粒子效果 |
CAGradientLayer |
梯度層,色彩坡形 |
CAEAGLayer |
用OpenGL ES繪製的層 |
CAReplicationLayer |
用來自動複製sublayer |
CAScrollLayer |
用來管理可滑動的地區 |
CAShapeLayer |
繪製立體的貝茲路徑 |
CATextLayer |
可以繪製AttributeString |
CATiledLayer |
用來管理一副可以被分割的大圖 |
CATransformLayer |
用來渲染3D layer的階層 |
管理Layer內容的幾個函數
addSublayer:
insertSublayer:above:
insertSublayer:atIndex:
insertSublayer:below:
removeFromSuperlayer
replaceSublayer:with:
三 直接設定UIView的Layer
先看一個樣本,然後我會列出常用的屬性,最後就某幾個比較不容易理解的屬性單獨分析。
先在Stroyboard上拖拽一個UIView,然後control+drag出一個IBOutlet,命名為containView
@property (weak, nonatomic) IBOutlet UIView *containView;
然後,在ViewDidLoad中,鍵入如下代碼
containView.layer.backgroundColor = [UIColor lightGrayColor].CGColor;//背景色 containView.layer.cornerRadius = 20.0;//圓角 containView.layer.shadowColor = [UIColor blueColor].CGColor;//陰影顏色 containView.layer.shadowOpacity = 0.8;//陰影透明度 containView.layer.shadowOffset = CGSizeMake(3.0, 3.0);//陰影的位移量 containView.layer.borderColor = [UIColor redColor].CGColor;//邊界顏色 containView.layer.borderWidth = 2;//邊界寬度
這樣,運行後的效果
四 添加Sublayer
containView.layer.backgroundColor = [UIColor lightGrayColor].CGColor; containView.layer.cornerRadius = 20.0; containView.layer.shadowColor = [UIColor blueColor].CGColor; containView.layer.shadowOpacity = 0.8; containView.layer.shadowOffset = CGSizeMake(3.0, 3.0); containView.layer.borderColor = [UIColor redColor].CGColor; containView.layer.borderWidth = 2; CALayer * sublayer1 = [CALayer layer]; sublayer1.backgroundColor = [UIColor blueColor].CGColor; sublayer1.frame = CGRectMake(0, 0,80,80); sublayer1.anchorPoint = CGPointMake(0.5, 0.5); sublayer1.position = CGPointMake(100,100); [containView.layer addSublayer:sublayer1];
有可能添加Sublayer的時候,sublayer的frame範圍已經超過了super Layer的frame,那麼會怎麼樣呢?
sublayer1.position = CGPointMake(0,CGRectGetMaxY(containView.bounds)-10);
修改sublayer1的位置,然後效果
但是,很多時候我們並不想sublayer的範圍超出 super layer,這時候可以設定這個屬性
containView.layer.masksToBounds = YES;
效果
這裡再聽過兩個常用的CALayer的子類UIShapeLayer和UITextLayer的樣本
CAShapeLayer * shapeLayer = [CAShapeLayer layer]; CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path,nil,0.0,0); CGPathAddLineToPoint(path,nil,0.0,CGRectGetHeight(containView.bounds)/2); shapeLayer.path = path; shapeLayer.bounds = CGRectMake(0,0,5.0,CGRectGetHeight(containView.bounds)/2); shapeLayer.anchorPoint = CGPointMake(0.5, 0.5); shapeLayer.position = CGPointMake(CGRectGetMidX(containView.bounds),CGRectGetMidY(containView.bounds)); shapeLayer.lineWidth = 5.0; shapeLayer.lineCap = kCALineCapRound; shapeLayer.strokeColor = [UIColor yellowColor].CGColor; [containView.layer addSublayer:shapeLayer]; CATextLayer * textLayer = [CATextLayer layer]; NSString * text = @"blog.csdn.net/hello_hwc"; NSAttributedString * attributeString = [[NSAttributedString alloc] initWithString:text]; textLayer.string = text; textLayer.alignmentMode = @"center"; textLayer.fontSize = 12; textLayer.foregroundColor = [UIColor brownColor].CGColor; CGRect bounds; bounds.origin = CGPointMake(0, 0); bounds.size = attributeString.size; textLayer.bounds = bounds; textLayer.position = CGPointMake(100,100); [containView.layer addSublayer:textLayer];
五 anchorPoint和position
和UIView不同,Layer主要由三個屬性來設定位置(極少用Frame):
bounds - 設定大小
anchorPoint -設定錨點(錨點對後續的layer動畫有很大影響)
position - 錨點在superLayer中的位置
這樣說有點抽象,我們看看以下的圖就瞭解了
對於IOS來說,座標系,archPoint(x,y)的兩個值通常取0.0-1.0,預設值是(0.5,0.5)這裡的值可以看作所佔用x的比例,比如預設的0.5,0.5就是在x的中間和y的中間。
而position則是AnchorPoint在super layer中的位置
如
五 Layer顯示圖片
CALayer * imageLayer = [CALayer layer]; imageLayer.bounds = CGRectMake(0,0,200,100); imageLayer.position = CGPointMake(200,200); imageLayer.contents = (id)[UIImage imageNamed:@"lichen.jpg"].CGImage; imageLayer.contentsGravity = kCAGravityResizeAspect; [containView.layer addSublayer:imageLayer];
這裡,要詳細講解以下contentGravity這個屬性。這個屬性決定了contents如何填充。
具體分為兩個方面,
方面一,位置方面
具體
方面二,比例變換方面
六 Layer於UIView的區別
摘自官方文檔
Layers are not a replacement for your app’s views—that is, you cannot create a visual interface based solely on layer objects. Layers provide infrastructure for your views. Specifically, layers make it easier and more efficient to draw and animate the contents of views and maintain high frame rates while doing so. However, there are many things that layers do not do. Layers do not handle events, draw content, participate in the responder chain, or do many other things. For this reason, every app must still have one or more views to handle those kinds of interactions.
In iOS, every view is backed by a corresponding layer object but in OS X you must decide which views should have layers. In OS X v10.8 and later, it probably makes sense to add layers to all of your views. However, you are not required to do so and can still disable layers in cases where the overhead is unwarranted and unneeded. Layers do increase your app’s memory overhead somewhat but their benefits often outweigh the disadvantage, so it is always best to test the performance of your app before disabling layer support.
簡單來說,View和Layer最大的區別就是View可以接受使用者輸入(例如觸摸)而Layer不可以,Layer單獨並不能呈現出任何可視的內容,必須依託於View。Layer只是幾何上呈現給使用者的東西,它較為輕量,通常採用Cache技術,對資源消耗也較小。
七 接下來的計劃
下一篇會繼續更新CALayer,更新一些不常用的屬性和方法,然後更新Core Animation的內容