我是大自然的搬運工,處女第二篇(筆記篇-轉(zhuǎn)載別人的)
什么是CALayer吕喘?
CALayer(這里簡單地稱其為層)漂辐。
首先要說的是CALayers 是屏幕上的一個具有可見內(nèi)容的矩形區(qū)域显拳,每個UIView都有一個根CALayer括细,
其所有的繪制(視覺效果)都是在這個layer上進行的伪很。
UILabel* lable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];
lable.text = @"test";
[self.view addSubview: lable];
lable.backgroundColor = [UIColor clearColor];
[lable release];
// 設定CALayer
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor;
self.view.layer.cornerRadius =20.0;
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
請注意,我創(chuàng)建的UILable始終隨著UIView的根CALayer的縮放而改變位置奋单。)
其次锉试,CALayer的可以影響其外觀的特性有:層的大小尺寸背景色內(nèi)容(比如圖像或是使用Core Graphics 繪制的內(nèi)容)是否使用圓角是否使用陰影等等.需要說明的是CALayer的大部分屬性都可以用來實現(xiàn)動畫效果。
另外览濒,你可以直接使用CALayer呆盖,也可以使用其子類,如CAGradientLayer贷笛,CATextLayer应又, CAShapeLayer等等。
1乏苦、示例
首先在Xcode中創(chuàng)建一個View-based App株扛,CALayer是屬于QuartzCore framework的,所以需要引入QuartzCore framework汇荐,另外在程序中包括QuartzCore.h洞就。
第一個例子是創(chuàng)建一個帶圓角的層,在你的ViewController中的ViewDidLoad中加入下面代碼:
// Import QuartzCore.h at the top of the file
#import
// Uncomment viewDidLoad and add the following lines
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor;
self.view.layer.cornerRadius =20.0;
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
然后添加一個帶陰影效果的子層掀淘,加入下列代碼:
CALayer *sublayer = [CALayer layer];
sublayer.backgroundColor = [UIColor blueColor].CGColor;
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 0.8;
sublayer.frame = CGRectMake(30, 30, 128, 192);
[self.view.layer addSublayer:sublayer];
//為子層增加內(nèi)容(圖片)旬蟋,你還可以設置層的邊框,代碼如下:
sublayer.contents =(id)[UIImage imageNamed:@"BattleMapSplashScreen.png"].CGImage;
sublayer.borderColor =[UIColor blackColor].CGColor;
sublayer.borderWidth =2.0;
如 果你希望子層也是圓角怎么辦革娄?你可能說很容易設置cornerRadius屬性就行倾贰。實際上你即算是設置了cornerRadius屬性,圖片仍然不會顯 示圓角拦惋。你還需要設置masksToBounds為YES躁染。但是這樣做還是不夠的,因為如果是這樣架忌,這個層的陰影顯示就沒有了吞彤。簡單的實現(xiàn)方法如下(通過 兩個層來實現(xiàn)):
CALayer *sublayer =[CALayer layer];
sublayer.backgroundColor =[UIColor blueColor].CGColor;
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius =5.0;
sublayer.shadowColor =[UIColor blackColor].CGColor;
sublayer.shadowOpacity =0.8;
sublayer.frame = CGRectMake(30, 30, 128, 192);
sublayer.borderColor =[UIColor blackColor].CGColor;
sublayer.borderWidth =2.0;
sublayer.cornerRadius =10.0;
[self.view.layer addSublayer:sublayer];
CALayer *imageLayer =[CALayer layer];
imageLayer.frame = sublayer.bounds;
imageLayer.cornerRadius =10.0;
imageLayer.contents =(id)[UIImage imageNamed:@"BattleMapSplashScreen.png"].CGImage;
imageLayer.masksToBounds =YES;
[sublayer addSublayer:imageLayer];
最 后,還介紹一下自繪圖型的實現(xiàn)叹放,其要點是要設置所繪制層的delegate饰恕。比如在我們的例子中使用ViewController作為delegate, 那么就需要在ViewController中實現(xiàn)drawLayer:inContext方法井仰,對層進行繪制工作埋嵌。另外,還需要調(diào)用 setNeedsDisplay俱恶,來通知層需要進行繪制了雹嗦,于是層才會通過對delegate的drawLayer:inContext方法進行調(diào)用范舀。
代碼如下:
void MyDrawColoredPattern (void*info, CGContextRef context){
CGColorRef dotColor =[UIColor colorWithHue:0 saturation:0 brightness:0.07 alpha:1.0].CGColor;
CGColorRef shadowColor =[UIColor colorWithRed:1 green:1 blue:1 alpha:0.1].CGColor;
CGContextSetFillColorWithColor(context, dotColor);
CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 1, shadowColor);
CGContextAddArc(context, 3, 3, 4, 0, radians(360), 0);
CGContextFillPath(context);
CGContextAddArc(context, 16, 16, 4, 0, radians(360), 0);
CGContextFillPath(context);
}
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
CGColorRef bgColor =[UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
CGContextSetFillColorWithColor(context, bgColor);
CGContextFillRect(context, layer.bounds);
staticc*****t CGPatternCallbacks callbacks ={0, &MyDrawColoredPattern, NULL};
CGContextSaveGState(context);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace(context, patternSpace);
//還需要注意,radians是一個自定義函數(shù):
static inline double radians (double degrees) { return degrees * M_PI/180; }
_______________________________________CALayer_______________________________________
1了罪、CALayer 這個類么锭环,和UIView有什么區(qū)別和聯(lián)系?Layer到底是個什么東西泊藕?
答:就是層啊辅辩,這個層你隨便控制他的大小,旋轉(zhuǎn)娃圆,角度玫锋,坐標變化或者內(nèi)容之類的信息,這些變化還可以通過動畫表現(xiàn)出來讼呢。
UIView所有你能看到的顯示的內(nèi)容撩鹿,后面都有一個Layer。
UIView 的animation我覺得是一種簡化悦屏,實質(zhì)還是調(diào)用的 CALayer 三痰。
每個層都可以設定單獨的動作,還可以給上一級的層設置動作窜管,下一級的層就可以跟著上一層進行動作。
CALayer是為更好實現(xiàn)View的動畫稚机,比如你想View消失時做成玻璃破碎的效果幕帆,
就可以在View的CALayer上密密麻麻排一層N個小的子CALayer, 設置每個CALayer的落下動畫赖条,用View就比較不合適失乾。
一個UIView包含CALayer樹,CALayer是一個數(shù)據(jù)模型纬乍,包含了一些用于顯示的對象碱茁,但本身不用于顯示。
2仿贬、CALayer和UIView的關系?
一個UIView包含CALayer樹纽竣,CALayer是一個數(shù)據(jù)模型,包含了一些用于顯示的對象茧泪,但本身不用于顯示蜓氨。
CALayer相當于photoshop的一個層,很多動畫可以通過設置CALayer來實現(xiàn)队伟。據(jù)說有人用CALayer顯示圖片來播放視頻穴吹。
Core animation應該是用CAlayer來實現(xiàn)各種動畫。
3嗜侮、UIView 與CALayer的區(qū)別?
- UIView是iOS系統(tǒng)中界面元素的基礎港令, 所有的界面元素都繼承自它啥容。它本身完全是由CoreAnimation來實 現(xiàn)的(Mac下似乎不是這樣)。它真正的繪圖部分顷霹,是由一個叫CALayer(Core Animation Layer)的類來管理咪惠。UIView本身,更像是一個CALayer的管理器泼返,訪問它的跟繪圖和跟坐標有關的屬性硝逢,例如frame,bounds等等绅喉,實際上內(nèi)部都是在訪問它所包含的CALayer的相關屬性渠鸽。
2.UIView有個layer屬性,可以返回它的主CALayer實例柴罐,UIView有一個layerClass方法徽缚,返回主layer所使用的類,UIView的子類革屠,可以通過重載這個方法凿试,來讓UIView使用不同的CALayer來顯示,例如通過
- (class) layerClass {
return ([CAEAGLLayer class]);
}
使某個UIView的子類使用GL來進行繪制似芝。
3.UIView的CALayer類似UIView的子View樹形結(jié)構(gòu)那婉,也可以向它的layer上添加子layer,來完成某些特殊的表示党瓮。例如下面的代碼
grayCover = [[CALayer alloc] init];
grayCover.backgroundColor = [[[UIColor blackColor] colorWithAlphaComponent:0.2] CGColor];
[self.layer addSubLayer: grayCover];
會在目標View上敷上一層黑色的透明薄膜详炬。
4.UIView的layer樹形在系統(tǒng)內(nèi)部,被系統(tǒng)維護著三份copy(這段理解有點吃不準)寞奸。
第一份呛谜,邏輯樹,就是代碼里可以操縱的枪萄,例如更改layer的屬性等等就在這一份隐岛。
第二份,動畫樹瓷翻,這是一個中間層聚凹,系統(tǒng)正在這一層上更改屬性,進行各種渲染操作齐帚。
第三份元践,顯示樹,這棵樹的內(nèi)容是當前正被顯示在屏幕上的內(nèi)容童谒。
這三棵樹的邏輯結(jié)構(gòu)都是一樣的单旁,區(qū)別只有各自的屬性。
5.動畫的運作
UIView的主layer以外(我覺得是這樣)饥伊,對它的subLayer象浑,也就是子layer的屬性進行更改蔫饰,系統(tǒng)將自動進行動畫生成,動畫持續(xù)時間有 個缺省時間愉豺,個人感覺大概是0.5秒篓吁。在動畫時間里,系統(tǒng)自動判定哪些屬性更改了蚪拦,自動對更改的屬性進行動畫插值杖剪,生成中間幀然后連續(xù)顯示產(chǎn)生動畫效果。
6.坐標系系統(tǒng)(對position和anchorPoint的關系還是犯暈)
CALayer的坐標系系統(tǒng)和UIView有點不一樣驰贷,它多了一個叫anchorPoint的屬性盛嘿,它使用CGPoint結(jié)構(gòu),但是值域是0~1括袒,也就是 按照比例來設置次兆。這個點是各種圖形變換的坐標原點,同時會更改layer的position的位置锹锰,它的缺省值是{0.5, 0.5}芥炭,也就是在layer的中央。
某layer.anchorPoint = CGPointMake(0.f, 0.f);
如果這么設置恃慧,layer的左上角就會被挪到原來的中間的位置园蝠,
加上這樣一句就好了
某layer.position = CGPointMake(0.f, 0.f);
7.真實例子的分析
這是iphone上iBook翻頁的效果,假設每一頁都是一個UIView痢士,我覺得一個頁面是貼了倆個Layer彪薛,文字Layer顯示正面的內(nèi)容,背面 layer用文字layer的快照做affine翻轉(zhuǎn)良瞧,貼在文字layer的后面。因為Layer可以設置顯示陰影训唱,也許后面的陰影效果沒有使用單獨的一 個layer來顯示褥蚯。至于這個曲面效果,我查了很多資料也沒有結(jié)果况增,估計是使用了GL的曲面繪圖赞庶?
8.最后一個
layer可以設置圓角顯示,例如UIButton的效果澳骤,也可以設置陰影顯示歧强,但是如果layer樹中的某個layer設置了圓角,樹中所有l(wèi)ayer 的陰影效果都將顯示不了了为肮。如果既想有圓角又想要陰影摊册,好像只能做兩個重疊的UIView,一個的layer顯示圓角颊艳,一個的layer顯示陰 影.....