Custom Drawing
CALayer 有一個代理 CALayerDelegate。如果想要CALayer 去重繪可以嘗試調(diào)用 ** -(void)displayLayer:(CALayer *)layer ** 方法。這個方法會調(diào)用 ** -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx ** 方法,可以在此方法中實現(xiàn)自定義繪制圖形。例如:
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextSetLineWidth(ctx, 10.0f); //設(shè)置線的寬度
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor); //設(shè)置填充顏色
CGContextStrokeEllipseInRect(ctx, layer.bounds); //填充的形狀、位置。
}
Layout
UIView 和 CALayer 擁有相似的布局屬性。都有frame,bounds. CALayer 的 position 也對應(yīng) UIView 的center 屬性。 看下圖:
frame 和 bounds 的區(qū)別在于看參照的對象。frame 是外部,而 bounds 是內(nèi)部。
我們旋轉(zhuǎn)一定角度再看。(可以看到 frame 發(fā)生了變化)
UIView 的 center 和 CALayer 的 position 屬性,都是相對于 layer 的anchorPoint 屬性的。和我們前面提到的 contentsCenter 時一樣, anchorPoint 也是使用 unit 計算單元。就是說他的值在 0-1 之間。
看下圖,了解一下移動前后,anchorPoint 的變化。
下面,我們通過一個表盤實例,了解一下 anchorPoint 的具體應(yīng)用。
如下圖,這是原始素材,由4張圖片組成。4張圖片,對其、堆起后的效果如圖。
將指針的圖片,旋轉(zhuǎn)相應(yīng)的角度后,得到下圖。顯然,問題出來了,這樣旋轉(zhuǎn)不是一個表應(yīng)該的樣子。
通過調(diào)整三張圖片的 anchorPoint 屬性值,設(shè)置為 CGPointMake(0.5f, 0.9f) 后,效果如下圖。
這就對了。
Coordinate Systems
CALayer 擁有和 UIView 相似坐標(biāo)系統(tǒng),都是相對于其父類的。有時候,我們需要找到它的具體位置,可以使用下面的4個方法。
-(CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;
-(CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;
-(CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
-(CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;
反轉(zhuǎn)坐標(biāo)系
這里順便提一下,在 iOS 系統(tǒng)中,position 都是相對于其父類的左上角而言的,而在 Mac 系統(tǒng)中,坐標(biāo)系是相對于其父類的左下角而言的。通過設(shè)置 CALayer的 ** geometryFlipped ** 屬性,可以實現(xiàn)發(fā)轉(zhuǎn)坐標(biāo)系的作用。
The Z Axis
UIView 是一個2維的坐標(biāo)系,而 CALayer 是 3維的。除了 position 和 anchorPoint ,CALayer 還擁有一個 zPosition 和 anchorPointZ 屬性。這里的Z軸的概念,類似與 Potoshop 中層的概念。你可以把 layer 想象為一層層的紙疊在一起。zPosition的值越大越靠上,如果不是透明,就會蓋住下面的層。
Automatic Layout
在 iOS 6 中,蘋果引入了 autolayout 的概念,不過,autolayout 是用與 UIView 的,CALayer 并沒有類似概念。如果某些情況下,我們需要改變 subLayer 的 position 或 frame 屬性怎么辦呢?可以調(diào)用 CALayerDelegate 的 ** -(void)layoutSublayersOfLayer:(CALayer*)layer ** 方法。該方法會在 layer 的 bounds 改變,或者手動調(diào)用了 ** -setNeedsLayout ** 方法后執(zhí)行。
Rounded Corners
看下面的代碼
self.layerView1.layer.cornerRadius = 20.0f; //圓角的大小
self.layerView2.layer.cornerRadius = 20.0f;
self.layerView2.layer.masksToBounds = YES; // 會裁切掉layerView2 bounds外的內(nèi)容
self.layerView1.layer.borderWidth = 5.0f; // 描邊的粗細(xì)
Drop Shadows
CALayer 的陰影由這幾個屬性來設(shè)置 shadowColor, shadowOffset, shadowRadius.
shadowColor 控制陰影的顏色。shadowOffset 控制著陰影的方向和大小。他是一個 CGSize 值,默認(rèn)為{0,-3}. 分別代表x軸的偏移量和y軸的偏移量。shadowRadius 控制陰影的模糊度。
這里有一個注意事項,如果使用了前面的masksToBounds 會同時把內(nèi)容和陰影都裁掉,這個容易理解,但并不是我們想要的結(jié)果。解決的方法是,再多添加一個 layer.
The shadowPath Property
陰影并不總是一個矩形,會根據(jù)內(nèi)容來自動繪制。比如說內(nèi)容是一個由 Alpha 通道的圖片,那么會根據(jù)不通明部分的形狀來繪制陰影。這樣會相當(dāng)?shù)暮馁M(fèi)CPU??梢酝ㄟ^ shadowPath 的屬性來設(shè)置背景的形狀。例如下面的代碼,一個繪制了矩形一個繪制了圓形的陰影。
self.layerView1.layer.shadowOpacity = 0.5f;
self.layerView2.layer.shadowOpacity = 0.5f;
//create a square shadow
CGMutablePathRef squarePath = CGPathCreateMutable();
CGPathAddRect(squarePath, NULL, self.layerView1.bounds);
self.layerView1.layer.shadowPath = squarePath;
CGPathRelease(squarePath);
//create a circular shadow
CGMutablePathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);
self.layerView2.layer.shadowPath = circlePath;
CGPathRelease(circlePath);