CoreAnimation 寄宿圖 博客園makedown支持不佳,如有需要請進 "GitHub" . 寄宿圖:圖層中所包含的圖 by:旭寶愛吃魚 針對於寄宿圖我在這裡只討論contents屬性以及Custom Drawing. contents &n ...
CoreAnimation 寄宿圖
博客園makedown支持不佳,如有需要請進GitHub.
寄宿圖:圖層中所包含的圖 by:旭寶愛吃魚
針對於寄宿圖我在這裡只討論contents屬性以及Custom Drawing.
contents
content:內容
CALayer的contents
屬性是一個id
類型.
@property(nullable, strong) id contents;
因此,可以將任何類型的對象賦值給contents
,但是如果將非CGImage類型的對象賦值給contents
將會的到一個空白頁.contents
之所以會存在這種現象是因為Mac OS的歷史原因造成的.
原因: contents
對CGImage類型的對象以及NSImage類型的對象都起作用!
然而問題並不是只有這麼一點點,我們可以嘗試將UIImage的CGImage賦值給contents
,不幸的是將會得到一個編譯報錯,產生錯誤的原因是CGImage返回的CGImageRef並不是一個Cocoa對象而是CoreFoundation類型,這時我們需要用bridged關鍵字進行轉換(MRC下不需要).
layer.contents = (__bridge id)image.CGImage;
下麵我們把一張圖片賦值給contents
.
為了便於對比我將原圖粘貼於此
- (void)viewDidLoad {
[super viewDidLoad];
UIImage * layerImage = [UIImage imageNamed:@"goddess"];
// 在圖層上添加圖片
self.customView.layer.contents = (__bridge id)layerImage.CGImage;// 圖片一
}
展示效果如下:
通過兩行代碼我們將GODDESS添加到圖層之上,但是與原圖相比我們發現goddess變胖了許多,我們不希望見到這中效果,因此我們需要對contentGravity
屬性進行設置.
contentGravity
contentGravity:圖層的展示類型.
CALayer的contentsGravity
屬性是一個NSString
類型.
@property(copy) NSString *contentsGravity;
contentsGravity
並沒有採取枚舉類型的賦值方式,因此我在這裡列出其相應的賦值範圍.
- kCAGravityCenter
- kCAGravityTop
- kCAGravityBottom
- kCAGravityLeft
- kCAGravityRight
- kCAGravityTopLeft
- kCAGravityTopRight
- kCAGravityBottomLeft
- kCAGravityBottomRight
- kCAGravityResize
- kCAGravityResizeAspect
- kCAGravityResizeAspectFill
為了改變上面結果的缺陷我們添加以下代碼:
layer.contentsGravity = kCAGravityResizeAspect;
得到以下效果:
contentsScale
contentsScale:像素尺寸與試圖大小的比例(預設1.0).
contentsScale
屬性是為了適配高分辨的屏幕機制,如果我們將其設置為1.0我們的得到的便是一個點由兩個像素組成,如果將其設置為2.0我們得到的便是一個點由兩個像素組成.
一般狀態下我們設置的方式如下:
layer.contentsScale = [UIScreen mainScreen].scale;
註意:
當我們能設置contentsGravity
自動拉伸類狀態時,設置contentsScale
是沒有效果的,因為contentsGravity
已經對圖層的展示進項了拉伸適配,如果我們需要查看設置contentsScale
的效果我們可以將contentsGravity
設置為kCAGravityCenter;
maskToBounds
maskToBounds:
YES(不展示圖層以外的內容)
NO(展示圖層以外的內容)
代碼示例:
layer. maskToBounds = YES;
iOS視圖預設允許我們將一個尺寸較大的圖層添加到一個尺寸較小的圖層上並加以展示,但是此時處於父圖層以外的子圖層區域的點擊等交互事件是監聽不到的,以及其他展示效果的影響我們在許多非正常佈局的情況下我們需要將maskToBounds
設置為YES.或者UIView的clipsToBounds
屬性設置為YES.
contentsRect
contentsRect:允許在圖層範圍內顯示寄宿圖的一個子域.
{x,y,w,h} 四個參數的取值範圍是0~1.
預設狀態下contentsRect
的取值是{0,0,1,1},也就是預設狀態下是顯示整個寄宿圖,也就是如下圖的效果.
如我我們將contentsRect
的取值設置為{0.5, 0.5, 0.5, 0.5},效果就變成如下圖所示:
在app中contentsRect比較典型的用法就是圖片拼合用法,也就是我們所需要展示的許多內容都在一張Image上,但是展示時通過contentsRect我們將他們一一取出,這樣就極大的節約了記憶體的使用率.
contentsCenter
contentsCenter:並不是contents的中心點,而是定義了一個固定的邊框和一個在圖層上可拉伸的區域.
contentsCenter
使用效果和UIImage里的-resizableImageWithCapInsets: 方法效果非常類似,但是它可以運用到任何寄宿圖,甚至包括在Core Graphics運行時繪製的圖形,在這裡就不多贅述具體的操作方法.
Custom Drawing
Custom Drawing:自定義繪製.
UIView-drawRect
-drawRect
並不是一個十分陌生的方法,每當我麽自定義UIView的時候都可一看到他的身影,他的本身含以也正如我們自定義UIView的意圖,我們可以通過他實現自定義繪製寄宿圖.
-drawRect:
方法是沒有被蘋果預設實現的,因為對與UIView來說,寄宿圖不是他所必須.如果UIView檢測到-drawRect:
方法被實現了,那麼UIView會為視圖分配一個寄宿圖,寄宿圖的像素尺寸等於視圖大小乘以 contentsScale
的值。需要註意的是如果我們不需要使用寄宿圖我們不要實現-drawRect:
,因為這會造成CPU以及記憶體的不必要浪費,當然apple也是這麼建議的.
-drawRect:
的調用是在視圖出現在屏幕的時候,-drawRect:
利用其封裝的代碼通過CoreGraphics來繪製一個寄宿圖,當寄宿圖繪製結束後會被緩存起來,直到它需要更新的時候(通過調用-setNeedsDisplay
)去重新繪製更新.
CALayer-displayLayer:
&&-drawLayer:inContext:
-displayLayer:
對象方法
-drawLayer:inContext:
代理方法
我們可以通過CALayerDelegate
的-drawLayer:inContext:
來實現自定義繪製圖層.需要做的內容很簡單,設置layer的代理,然後實現-drawLayer:inContext:
方法,當我們需要更新繪製的時候調用-displayLayer:
即可.
註意:
- CALayer不同於UIView,當圖層顯示在屏幕上時,CALayer不會自動重繪它的內容,它把重繪的決定權交給了開發者。
- 當使用CALayerDelegate繪製寄宿圖的時候,並不會對超出邊界外的內容進行繪製。