CALayer的簡單使用


原文地址:http://www.raywenderlich.com/2502/calayers-tutorial-for-ios-introduction-to-calayers-tutorial


如果你已經在iPhone上做過開發,你可能對UIView和它的子類-Button,text,slider等,非常熟悉。

但你可能不瞭解UIView是建立在CALayers之上的,至少我曾經有段時間不知道。
瞭解CALayers是有用的,因爲你可以使用它們輕鬆地去創造一些純視覺效果,它們對理解使用將在未來教程中討論的Core Animation也很重要。
在CALayers的教程中,你將通過做創造一個層並實驗它的效果的簡單APP去學習基本的層的使用,在這個過程中,你將學到層是什麼,一些能設置的純屬性和如何將圖像和自定義內容放入層裏。

這個層的教程假設你基本熟悉iPhone編程,如果你是新手,可以從如何創建一個簡單的iPhone App開始。
讓我們開始吧

什麼是層?

層是表現一個在屏幕上的包含可視內容的矩形的簡單類。
“等一下”,你可能說,“這是UIView的定義”,是這樣的,但這兒有個把戲:每一個UIView包含一個用於繪製的根層,你可以使用下面的代碼訪問這個自動創造的層:(CALayer是UIView的根基)
CALayer *myLayer = myView.layer;
CALayer類包含了很多可設置的影響外觀顯示的屬性,例如:
層的尺寸和位置
層的背景顏色
層的內容(圖像或者使用Core Graphics繪製的)
是否是圓角層
在層的邊緣應用邊框
更多內容
你可以使用這些屬性去創造一些效果,例如你想拿一副圖片,放在白色的邊框,應用一個陰影效果,使其更爲逼真,而不是拿出Photoshop或寫一堆Core Graphicsdaima代碼,你可以使用層的代碼。
另外層的屬性,多數是可以動畫的,例如,你可以開始用圓角圖片,點擊按鈕,有個動畫效果,圓角變回直角,使用起來是非常方便簡單的。
你可以直接使用層類,或者你可以使用一個它的子類,例如CAGradientLayer, CATextLayer, CAShapeLayer,和其他。UIView默認的層類是CALayer類,這個是教程的重點。

開始

這兒去了解層的使用的最好方法是自己動手,所以啓動Xcode,選擇File\New Project,選擇 iOS\Application\View-Based Application,點"Choose",起名工程"Layer
Fun",點保存(就是創建個測試Layer的工程)。
添加QuzatCore,做下列改動到LayerFunViewController.m:
// Import QuartzCore.h at the top of the file
#import <QuartzCore/QuartzCore.h>
 
// 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);


讓我們一步一步回顧這些新東西
爲了得到view的層,你可以使用self.view.layer,記住,你可以使用self.view獲得view controller 的根視圖,你一旦得到視圖,你可以使用view.layer獲得默認的層(自動創建的),默認層是一個CALayer的類(不是子類)。
下一步你設置層的背景色爲橙色,注意背景色屬性實際是CGColor類型,但可以使用CGColor屬性從UIColor到CGColor轉換。
下一步你設置圓角的弧度,設置的這個值是製造圓角的圓的半徑,20是一個漂亮的圓角邊緣。
最終,你使用CGRectInset的功能,收縮一點frame,方便看到效果。CGRectInset函數收縮X和Y的座標,返回一個新的Frame。
編譯執行你的代碼,你可以在屏幕中央看到一個圓角橙色矩形。

層和子層

就像UIView可以有自視圖,CALayers可以也可以用子層,你可以使用下面的代碼創建一個新的層:
CALayer *sublayer = [CALayer layer];
一旦你擁有一個層,你可以在上面設置任何你想要的屬性,但是記住這兒有一個屬性你一定要設置:它是frame(或者bounds/ position)。畢竟,層需要去知道它有多大(在什麼位置),才能畫出自己。當你完成了,你可以把新的層當作子層添加到另一個層中,通過下面的代碼:
[myLayer addSublayer:sublayer];
好了,現在試着自己添加一個簡單的子層到view的層中,添加下面的代碼在viewDidLoad函數內之前添加代碼的後面:
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];

這創建了一個新的層,並且設置了一些屬性,包括一些之前沒設置過的陰影屬性,你可以看到在層上設置陰影是多麼簡單,通過這樣,可以用一點工作量完成令人驚奇的效果。(就是簡單、方便、有效果)
在設置了這些屬性,需要設置層的frame並且把它加到view的層中,記住這些座標是相對於父層的frame(父層座標體系的座標)如果父層位於(20,20),子層設置偏移(30,30),子層在屏幕的位置將會是(50,50).
編譯執行你的代碼,你將看到一個藍色子層在屏幕上。


設置層的圖像內容

CALayers可以包含更多的內容除了純顏色,它非常容易包含圖片內容,例如:
先將一張名爲“BattleMapSplashScreen.jpg”的圖片包含進項目
然後添加以下代碼:
sublayer.contents = (id) [UIImage imageNamed:@"BattleMapSplashScreen.jpg"].CGImage;
sublayer.borderColor = [UIColor blackColor].CGColor; 
sublayer.borderWidth = 2.0;


這裏設置了內容爲圖片的層,並且使用邊界的顏色和寬度設置了一圈黑色的邊界,演示了它如何工作。
編譯執行你的代碼,你可以看到藍色層的內容被圖片替換調了。

圓角半徑和圖片內容的注意點

現在你可能想通過cornerRadius把圖片也設置成圓角效果。
然而問題超過了咱們之前學的範圍,如果你在層上設置了圖片內容,圖像將仍然畫出圓角的邊界(該屬性起不了作用),你可以通過設置子層的masksToBounds爲Yes,但如果你這樣做,陰影效果將不會出現因爲他們被蓋掉了。

我找到一個創造兩個層的方法,在外的層是有邊框和陰影帶顏色的層,裏面的層包含圓角圖像和設置mask,這樣在外的層繪製陰影,在裏的層包含圖像。

試着使用下面的替換創建子層的代碼:
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.jpg"].CGImage;
imageLayer.masksToBounds = YES; 
[sublayer addSublayer:imageLayer];
編譯運行代碼,現在你的圖像將有圓角

層和自定義繪畫內容

如果你想使用Core Graphics替代圖片繪製自定義的層,也是很容易的。
方法是你設置一個類作爲層的代理對象,這個類實現名爲drawLayer:inContext的方法,裏面包含你想繪製內容的Core Graphics代碼。
讓我們試着添加一個新的層,在裏面畫一個圖案,你把層的代理指向view controller的對象,實現drawLayer:inContext的方法去畫圖案。
在你的viewDidLoad添加以下代碼建立一個新層:
CALayer *customDrawn = [CALayer layer];
customDrawn.delegate = self;
customDrawn.backgroundColor = [UIColor greenColor].CGColor;
customDrawn.frame = CGRectMake(30, 250, 128, 40);
customDrawn.shadowOffset = CGSizeMake(0, 3);
customDrawn.shadowRadius = 5.0;
customDrawn.shadowColor = [UIColor blackColor].CGColor;
customDrawn.shadowOpacity = 0.8;
customDrawn.cornerRadius = 10.0;
customDrawn.borderColor = [UIColor blackColor].CGColor;
customDrawn.borderWidth = 2.0;
customDrawn.masksToBounds = YES;
[self.view.layer addSublayer:customDrawn]; 
[customDrawn setNeedsDisplay];

這裏的代碼,大多數之前都出現過,就有兩點是新的:
1 第一 把層的委託設置給self,這以爲這個對象(self)將需要實現 drawLayer:inContext去繪製層的內容。
2 在添加層後,需要通過調用setNeedsDisplay通知層去刷新自己(並調用drawLayer:inContext),如果你忘記調用這個,drawLayer:inContext將不會被調用,圖案將不出現。
接下來添加代碼去實現drawLayer:inContext,如下:
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);
 
    static const CGPatternCallbacks callbacks = { 0, &MyDrawColoredPattern, NULL };
 
    CGContextSaveGState(context);
    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
    CGContextSetFillColorSpace(context, patternSpace);
    CGColorSpaceRelease(patternSpace);
 
    CGPatternRef pattern = CGPatternCreate(NULL,
                                           layer.bounds,
                                           CGAffineTransformIdentity,
                                           24,
                                           24,
                                           kCGPatternTilingConstantSpacing,
                                           true,
                                           &callbacks);
    CGFloat alpha = 1.0;
    CGContextSetFillPattern(context, pattern, &alpha);
    CGPatternRelease(pattern);
    CGContextFillRect(context, layer.bounds);
    CGContextRestoreGState(context); 
}


就是這樣,運行代碼,你將在圖片下面看到一個藍色的圖案

將來





發佈了80 篇原創文章 · 獲贊 278 · 訪問量 142萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章