-
contents是一個類型為id的屬性,在iOS開發(fā)中,可以利用這個屬性給CALayer設(shè)置backing image。需要用CGImageRef類型的值給contents賦值,不然沒有效果。賦值后,CALayer會顯示一張圖片:
UIImage *image = [UIImage imageNamed:@"我是一張圖片.JPEG"];
view.layer.contents = (__bridge id)image.CGImage;
- 使用UIImageView和CALayer顯示圖片的時候,當(dāng)frame的size和圖片的size長寬比不一致的時候,就會出現(xiàn)圖片被拉伸的情況。
UIView有一個命名為contentMode的屬性,可以設(shè)置圖片的顯示方式。對應(yīng)于contentMode,CALayer的屬性為contentsGravity。但contentMode是一個枚舉類型,而contentsGravity接受的是一個字符串類型,可選的常量值為kCAGravityResizeAspect等。給contentMode賦值UIViewContentModeScaleAspectFit或者給contentsGravity賦值kCAGravityResizeAspect,就可以避免圖片出現(xiàn)拉伸的情況。 -
contentsScale屬性是支持高分辨率屏幕機(jī)制的一部分。它的默認(rèn)值為1.0,即會以每個點一個像素繪制圖片。如果設(shè)置成2.0,則會以每個點2個像素繪制圖片。但需要注意的是,如果設(shè)置了contentMode或者contentsGravity為一些值時(例如kCAGravityResizeAspect或者UIViewContentModeScaleAspectFit),對于contentsScale的設(shè)置會沒有效果。 - 當(dāng)
CALayer顯示的內(nèi)容超過了圖層本身的frame時,可以通過設(shè)置maskToBounds為YES,這樣超過圖層本身frame的內(nèi)容就不會顯示。 -
UIImage是一個屏幕分辨率解決方案,所以指定點來度量大小。但是一些底層的圖片表示如CGImage就會使用像素,所以要清楚在Retina設(shè)備和普通設(shè)備上,他們表現(xiàn)出來了不同的大小。 -
CALayer的contentsRect屬性是一個可以讓圖層邊框顯示圖片的一部分區(qū)域。它不是按點來計算的,它使用了單位坐標(biāo),單位坐標(biāo)指定在0到1之間。默認(rèn)的contentsRect是{0, 0, 1,1},表示顯示圖片的全部區(qū)域。如果我們設(shè)定一個小一點的矩形,圖片就會被裁減。如果給contentsRect設(shè)置一個負(fù)數(shù)的原點或是大于{1, 1}的尺寸也是可以的。這種情況下,最外面的像素會被拉伸以填充剩下的區(qū)域。 -
CALayer的contentsCenter屬性是一個CGRect類型,它定義了一個固定的邊框和一個在圖層上可拉伸的區(qū)域。只有在圖片被拉伸后才會起作用。contentsCenter可以用來定義拉伸的范圍。 - 除了給使用
contents設(shè)置CALayer的backing image外,還可以使用Core Graphics進(jìn)行繪制。例如:
/*- (void)displayLayer:(CALayer *)layer{
UIImage *img = [UIImage imageNamed:@"我是一張圖片"];
layer.contents = (__bridge id)img.CGImage;
}*/
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextSetLineWidth(ctx, 20.0f);
CGContextSetStrokeColorWithColor(ctx, [UIColor blue].CGColor);
CGContextStrokeEllipseInRect(ctx, layer.bounds);
}
若代理實現(xiàn)了- (void)displayLayer:(CALayer *)layer,則可以在該方法中對圖層進(jìn)行設(shè)置,如注釋的代碼所示。若沒有實現(xiàn)- (void)displayLayer:(CALayer *)layer,則會調(diào)用代理的方法- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx。調(diào)用這個方法之前,CALayer會創(chuàng)建一個空的backing image和Core Graphics的繪制上下文環(huán)境,并作為代理方法的參數(shù)ctx。
可以發(fā)現(xiàn)上面的代碼顯示調(diào)用了CALayer的display方法。因為當(dāng)開發(fā)者手動創(chuàng)建一個圖層,并顯示在屏幕上時,CALayer不會自動重繪它的內(nèi)容。它把重繪的決定權(quán)交給了開發(fā)者。并且使用CALayerDelegate繪制時,并沒有對超出邊界外的內(nèi)容提供繪制支持。
- 對于
UIView來說,-(void)drawRect:(CGRect)rect方法是沒有默認(rèn)實現(xiàn)的。如果UIView檢測到子類實現(xiàn)了-(void)drawRect:(CGRect)rect方法,就會創(chuàng)建backing image。所以如果沒有自定義繪制的內(nèi)容,不要去實現(xiàn)-(void)drawRect:(CGRect)rect方法。這樣可以節(jié)省CPU和內(nèi)存資源。雖然-(void)drawRect:(CGRect)rect是UIView的一個方法,但事實上重繪的工作都是由底層的CALayer進(jìn)行的。當(dāng)UIView創(chuàng)建了它的圖層時,它就會自動地把圖層的delegate設(shè)置為它自己,并提供了一個- (void)displayLayer:(CALayer *)layer的實現(xiàn)。而UIView會在需要重繪的時候調(diào)用display方法。