前言
UIView實(shí)際上不是draws它自己在屏幕上,它其實(shí)是吧自己畫(huà)在layer
上面筑公。一個(gè)view不會(huì)經(jīng)常redraw,重畫(huà)雳窟。他的drawing是被保存起來(lái)的,cached匣屡,and the cached version of the drawing (thebitmap backing store) is used where possible.
the view's graphic context is actually the layer's graphics context.
layer extend the power of views.
In particular:// 詳細(xì)地
Layers have properies that affect drawing
A layer is the recipient and present of a view's drawing. you can modify how a view is drawn on the screen by accessing the layer's properties.使用layer的屬性封救,可以做到view不能做到的事情。Layers can be combined within a single view
view的伙伴layer捣作,可以包含額外的layers.因?yàn)閘ayers的目的是去繪畫(huà)誉结,描繪可見(jiàn)的元素在屏幕上,這樣來(lái)說(shuō)券躁,view可以合并多種的不同的碎片(layers的展現(xiàn))惩坑,這樣來(lái)說(shuō)可以讓繪制更加簡(jiǎn)單,可以讓繪制分工合作也拜。layers are the basis of animation
Animation allows you to add clarity, emphasis, and just plain coolness to yourinterface.
Layers are made to be animated;the "CA" in "CALayer" 表示的是"Core Animation"
View and Layer
一個(gè)view
的初始化以舒,伴隨著CALayer
的初始化÷可以通過(guò)view.layer
獲取蔓钟。layer
沒(méi)有相當(dāng)?shù)?code>view屬性,但是是layer
的代理(delegate
)卵贱。
改變潛在的layer
:
import UIKit
class CustomView: UIView {
override class var layerClass:AnyClass {
return CompassLayer.self // CustomView的潛在的layer也就是ComPassLayer滥沫,而不是CALayer了
}
}
A layer cannot apeear without a view.
每一個(gè)view
都有一個(gè)一個(gè)潛在的layer
侣集,他們緊密相連的。layer
扮演著view
的drawing
,是因?yàn)?code>layer的drawing
影響著兰绣。view
是layer
的代理世分。view
的屬性,通常是access the layer's 屬性缀辩。
i.e.
設(shè)置view.backgroundColor臭埋,實(shí)際上是設(shè)置layer 的backGroundColor,
我們可以直接layer's backgroundColor
而且雌澄,view's frame 實(shí)際上是layer's frame
注意: 一個(gè)CALayer
的代理(delegate
)是可以設(shè)置的(to an instance of any class adopting CALayerDelegate),但是UIView
和他的潛在的layer
有一個(gè)特殊的聯(lián)系斋泄。view
必須是他的潛在的layer
的delegate
.而且杯瞻,他一定不能是其他Layer
的代理镐牺。如果這樣做了,drawing
將會(huì)直接停止工作魁莉。
The view draws into its layer, and the layer caches that drawing; the layer can then be manipulated, cahnging the view's appearace, without necessarily asking the view to redraw itself.
when the view’s bounds size changes, the drawing system, by default, sim‐ply stretches or repositions the cached layer image, until such time as the view is toldto draw freshly (draw(_:)), replacing the layer’s content.
Layers and Sublayers:圖層和子圖層
A layer can have sublayer, a layer at most can have one superlayer.
thus, there is a tree of layers.
A view’s subview’s underlying layer is a sublayer of that view’s underlaying layer, justlike any other sublayers of that view’s underlying layer. // 一個(gè)view 的 子view 的潛在的layer 是這個(gè)view的layer 的潛在的layer的子layer.
layers都有clipsToBounds
的屬性睬涧,默認(rèn)是false,所以它可以伸出去。
Like a UIView, a CALayer has an isHidden property that can be set to take it and itssublayers out of the visible interface without actually removing it from its superlayer.
Manipulating the Layer Hierarchy:操作layer的層級(jí)
layers 生來(lái)有一套read和manupulate layer 的層級(jí)旗唁。
addSublayer(_:)
insertSublayer(_: at:)
insertSublayer(_:below:), insertSublaer(_:above:)
replaceSublayer(_:with:)
removeFromSuperlayer
不像view的subview屬性畦浓,a layer's sublayer property is writable; 因此,你能夠給一個(gè)layer很多sublayers 一次性检疫, 用指定給它的sublayers屬性讶请。可以remove 一個(gè)Layer的所有sublayers屎媳,設(shè)置他的sublayers 屬性為nil.
盡管一個(gè)layer的sublayers有一個(gè)順序(order),
但是這個(gè)并不是唯一的顯示次序夺溢。默認(rèn)的,它是烛谊,但是一個(gè)layer
也有一個(gè)zPosition
的屬性风响。它也決定了繪制次序。規(guī)則是丹禀,越低的zPosition
就繪制越早状勤,默認(rèn)的是0.0
,這個(gè)還是很有用處的双泪。
mainView.addSubview(iv)
iv.layer.zPosition = 1
坐標(biāo)系統(tǒng)也有相應(yīng)的方法:
convert(_: from:)
convert(_: to:)
Position a Sublayer
layer 的坐標(biāo)系統(tǒng)與view是相似的持搜,bounds, bounds origin 都在它的左上角。
然而焙矛,一個(gè)sublayer的position 在他的superlayer中并不是以center來(lái)描述的葫盼,不像view, 一個(gè)layer薄扁,沒(méi)有center的屬性剪返。
反而废累,一個(gè)sublayer的postion在他的父layer中是由兩個(gè)屬性定義的:
- position
a point expressed in the superlayer's coordinate system - anchorPoint
where the position point is located, 有關(guān)于layer的自己的bounds.it is a CGPoint describing a fraction(or multiple) of the layer's own bounds width and bounds height. (錨點(diǎn).x/layer's bounds's width,錨點(diǎn).y/layer's bounds's height).因此脱盲,(0.0, 0.0) 就是layer的左上角邑滨,(1.0, 1.0)就是layer的右下角
錨點(diǎn)的默認(rèn)位置是(0.5, 0.5),就會(huì)work like the view's center property.
想象sublayer是用別針別在他的superlayer上的钱反,別針別的這個(gè)點(diǎn)在sublayer上就是錨點(diǎn)(anchorPoint),在這個(gè)superlayer上就是(position)
a view's center 因此是 a layer's position 的一種特定狀態(tài)掖看。
layer 的 position 和 anchiroint 是相互獨(dú)立的。改變一個(gè)并不會(huì)改變另外的一個(gè)面哥。
a layer's frame is 純粹推斷出來(lái)的屬性哎壳。當(dāng)你get frame的時(shí)候,it is calculatedfrom the bounds size along with the position and anchorPoint.
When you set the frame, you set the bounds size and position.// 當(dāng)你設(shè)置frame尚卫,你就設(shè)置了bounds size 和 position
to position a sublayer so that it exactly overlaps its superlayer, you can just set the sublayer’s frame to the superlayer’s bounds
注意:a layer created in code(相對(duì)的是view的潛在layer) 有一個(gè)frame 和 bounds 是CGRect.zero 归榕,也不會(huì)被看見(jiàn),盡管當(dāng)你添加他在screen上面
CAScrollLayer
對(duì)于一個(gè)未轉(zhuǎn)換的圖層吱涉,它的bounds和它的frame是一樣的刹泄,frame屬性是由bounds屬性自動(dòng)計(jì)算而出的,所以更改任意一個(gè)值都會(huì)更新其他值怎爵。
這個(gè)鏈接解釋了CAScrollLayer:http://www.reibang.com/p/6598db897fb9
Layout of Sublayers:Sublayer布局
view的層級(jí)實(shí)際上是layer的層級(jí).
The positioning of aview within its superview is actually the positioning of its layer within its superlayer(the superview’s layer).
a view can be repositioned and resized automatically in accordance with its autoresizingMask
or through autolayout
based on its constraints.
這里有關(guān)于autoresizingMask的鏈接:http://www.cocoachina.com/ios/20141216/10652.html
因此特石,Layer是自動(dòng)布局,如果Layer是view的潛在layer.
Otherwise, there is no automatic layout for layers in iOS. The only option forlayout of layers that are not the underlying layers of views is manual layout that you perform in code.
當(dāng)一個(gè)layer需要布局(layout),不是因?yàn)樗?code>bounds改變了鳖链,也不是因?yàn)槟阏{(diào)用了setNeedsLayout
,you can respond in either of two ways:
- The layer's
layoutSublayers
method is called; to respond, overridelayoutSublayers
in your CALayer subclass - Alternatively(非此即彼)姆蘸,implement
layoutSublayers(of:)
in the layer's delegate.(如果layer是view的潛在layer,view就是layer的delegate)
For your layer to do effective manual layout of its sublayers,you will probably need a way to identify or refer to the sublayers.There is no layer equivalent of viewWithTag(_:)
, so such identification and reference is entirely up to you.A CALayer does have a name property that you might misuse for your own purpose. Key-Value coding in a special way,后面再談。
view‘s 潛在的layer.layoutSublayers()
或者layoutSublayers(of:)
是在view的·layoutSubviews
之后.Under autolayout, you must call super or else autolayout will break.
而且芙委,這些方法可能會(huì)被調(diào)用不止一次逞敷,在autolayout的過(guò)程中;if you’re looking for an automatically generated signal that it’s time to do manual layout of sublayers, a view layout event might be a better choice题山。
Drawing in a layer
最簡(jiǎn)單的讓什么東西現(xiàn)在在layer中是通過(guò)他的content
屬性.類比于imageView的image.
It is expexted to be CGImage
(or nil
, 表示沒(méi)有Image).所以我們也可以這樣寫(xiě):
let lay4 = CALayer()
let im = UIImage(named:"smiley")!
lay4.frame = CGRect(origin:CGPoint(180, 180), size:im.size)
lay4.contents = im.cgImage // 注意cg
mainView.layer.addSublayer(lay4)
如果設(shè)置layer的content為image兰粉,而不是cgImage,雖然不會(huì)爆粗,但是現(xiàn)實(shí)不出來(lái)的顶瞳。
有4個(gè)方法能夠?qū)崿F(xiàn)給layer的content去draw或者提供玖姑,與UIView的 draw(_:)
相似,a layer 是非常保守的慨菱,對(duì)于調(diào)用這些方法(你也不能直接調(diào)用他們).
當(dāng)layer調(diào)用這些方法焰络,我們可以這樣說(shuō),layer在重繪他自己.
- 如果layer的
needsDisplayOnBounds
屬性是false(默認(rèn)就是false)符喝,然后唯一的方法讓layer去重繪他自己是調(diào)用setNeedsDisplay
(或者setNeedsDisplayIn(_:)
)闪彼。盡管這樣或許不能讓layer立即重繪自己;if that;s crucial, then you will also calldisplayIfNeeded
. - 如果
needsDisplayOnBoundsChange
屬性是true,然后layer將會(huì)也重繪自己畏腕,當(dāng)layer的bounds改變(rather like a view’s .redrawcontent mode)
這里有四個(gè)方法能被調(diào)用缴川,當(dāng)一個(gè)layer重繪自己的時(shí)候;選擇一個(gè)區(qū)實(shí)現(xiàn)描馅,(don't try to combine them, you'll just confuse things)
display in subclass
你的CALayer的subclass能夠override display. there is no graphics context 此時(shí)此刻把夸,所以display
是非常有限的 to setting the contents image.
display(_:) in the delegate
你可以設(shè)置CALayer的delegate屬性,和實(shí)現(xiàn)display(_:)
in the delegate.與CALayer的display一樣铭污,there is no graphic context, so you will just be setting the contens image.
draw(in:) in a subclass
你的CALayer的subclass能夠override draw(in:)
.the parameter is a graphic context, 在里面你能夠直接draw;it is not automatically made the curent context.
draw(_: in:) in the delegate
Assigning a layer a contents image and drawing directly into the layer are, in effect,mutually exclusive. So:
- 假設(shè)layer的contents是image.image會(huì)馬上被顯示恋日,this image is shown immediately and replaces whatever drawing may have been displayed in the layer.
- 如果layer 重繪自己,
draw(in:)
或者draw(_: in:)
draws into layer,the drawing 將會(huì)替換layer中的contents,無(wú)論是Image還是其他的. - 如果layer重繪自己嘹狞,四個(gè)方法中沒(méi)有任何一個(gè)提供任何內(nèi)容的話岂膳,layer將會(huì)是empty.
如果是view的潛在layer,你通常不會(huì)使用4個(gè)方法中的任何一個(gè)方法去draw into 你的layer.你會(huì)使用view's draw(_:)
.然而,你能夠使用這些方法如果你實(shí)在想用.如果是這樣.你可能想去實(shí)現(xiàn)draw(_:)
這個(gè)方法無(wú)論如何磅网, 不使用那種實(shí)現(xiàn).
原因是這個(gè)引起layer
在適當(dāng)?shù)臅r(shí)候去重繪自己.
當(dāng)一個(gè)view
被sent setNeedsDisplay
-- including when the view first appears -- view的潛在layer
也被sent setNeedsDisplay
, 除非這個(gè)view沒(méi)有實(shí)現(xiàn)draw(_:)
(因?yàn)樵龠@種情況下谈截,他被假設(shè)承view重來(lái)不需要redrawing(重繪)).
所以,直接draw一個(gè)view的潛在layer知市,and 如果你想潛在的layer被自動(dòng)redisplayed傻盟, 當(dāng)view被告知redraw他自己.你應(yīng)該實(shí)現(xiàn)draw(_:) to do nothing.(this technique has no effect on sublayers of the underlying layer)
因此,下面這幾個(gè)方法是合法的嫂丙,但是不通常使用的for drawing into a view:
- the view subclass 實(shí)現(xiàn)一個(gè)空的
draw(_:)
,along with eitherdisplayLayer:
或者draw(_: in:)