3.圖層幾何學(xué)
3.1布局
UIView:? frame? ? bounds? center
CALayer:frame? ? bounds? position? anchorPoint
圖層中的position對應(yīng)視圖的center,代表同樣的值與含義峻凫,都代表了相對于父圖層anchorPoint所在的位置
當(dāng)對圖層做變換的時(shí)候蒂教,比如旋轉(zhuǎn),frame代表了覆蓋在圖層旋轉(zhuǎn)之后的整個(gè)軸對齊的矩形區(qū)域赫舒,也就是說frame的寬高可能和bounds不一致了
3.2錨點(diǎn)
anchorPoint點(diǎn)(錨點(diǎn))的值是用相對bounds的比例值來確定的,anchorPoint默認(rèn)位于圖層中心點(diǎn),即{0.5,0.5},anchorPoint也使用的單位坐標(biāo)奈搜,加入將anchorPoint放在左上角,即{0,0}盯荤,那么圖層將會(huì)向右下角的position方向移動(dòng)
視圖的center屬性和圖層position屬性都指定了anchorPoint相對于父圖層的位置媚污,圖層的anchorPoint通過position來控制它的frame位置,可以認(rèn)為anchorPoint是用來移動(dòng)視圖圖層的句柄
我們創(chuàng)建了一個(gè)layerView廷雅,通過改變它的anchorPoint(從默認(rèn)的{0.5耗美,0.5}到{0,0})來觀察其它的變化
++++++++++frame:{{20, 20}, {100, 200}},-----bounds:{{0, 0}, {100, 200}},+++++++++layer.frame:{{20, 20}, {100, 200}},----------layer.bounds:{{0, 0}, {100, 200}},++++++++center.x:70.000000,-------center.y:120.000000,++++++++++position.x:70.000000,----------position.y:120.000000,+++++++++anchorPoint.x:0.500000,---------anchorPoint.y:0.500000
第二次++++++++++frame:{{70, 120}, {100, 200}},-----bounds:{{0, 0}, {100, 200}},+++++++++layer.frame:{{70, 120}, {100, 200}},----------layer.bounds:{{0, 0}, {100, 200}},++++++++center.x:70.000000,-------center.y:120.000000,++++++++++position.x:70.000000,----------position.y:120.000000,+++++++++anchorPoint.x:0.000000,---------anchorPoint.y:0.000000
如上數(shù)據(jù)航缀,我們可以看出center和position都是視圖圖層的anchorPoint在父視圖圖層中的位置商架,單獨(dú)改變anchorPoint,視圖的frame改變芥玉,而center和position保持原位置不變
anchorPoint常常用于動(dòng)畫中改變視圖的transform蛇摸,改變anchorPoint之后,視圖會(huì)圍繞anchorPoint來旋轉(zhuǎn)
anchorPoint灿巧、position赶袄、frame之間的相對關(guān)系.
? frame中的X,Y表示sublayer左上角相對于supLayer的左上角的距離
? position中的X,Y表示sublay錨點(diǎn)相對于supLayer的左上角的距離
? anchorPoint中的X,Y表示錨點(diǎn)的x,y的相對距離比例值
當(dāng)確定錨點(diǎn),改變frame時(shí), position的值為:
position.x = frame.origin.x + anchorPoint.x * bounds.size.width揽涮;
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
確定錨點(diǎn), 改變position時(shí), frame的值為:
frame.origin.x = position.x - anchorPoint.x * bounds.size.width饿肺;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height蒋困;
改變錨點(diǎn), frame的值變化為
frame.origin.x = - anchorPoint.x * bounds.size.width + position.x;
frame.origin.y = - anchorPoint.y * bounds.size.height + position.y敬辣;
影響關(guān)系
? 錨點(diǎn)改變, position不影響, frame變化
? frame變化, 錨點(diǎn)不影響, position變化
? position變化, 錨點(diǎn)不影響, frame變化
3.3坐標(biāo)系
3.3.1 坐標(biāo)系
和視圖一樣雪标,圖層在圖層樹當(dāng)中也是相對于父圖層按層級關(guān)系放置,一個(gè)圖層的position依賴于它父圖層的bounds溉跃,如果父圖層發(fā)生移動(dòng)村刨,所有子圖層也會(huì)跟著移動(dòng)
如果要知道一個(gè)圖層的絕對位置,或者是相對于另一個(gè)圖層的位置撰茎,那么可以使用以下方法:
- (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;
這些方法可以把定義在一個(gè)圖層坐標(biāo)系下的點(diǎn)或者矩形轉(zhuǎn)換成另一個(gè)圖層坐標(biāo)系下的點(diǎn)或者矩形
3.3.2 翻轉(zhuǎn)的幾何結(jié)構(gòu)
常規(guī)來講嵌牺,ios中,一個(gè)圖層的position位于父圖層的左上角龄糊,OS中髓梅,是位于左下角,CALayer有一個(gè)geometryFlipped屬性绎签,如果設(shè)置為YES枯饿,那么此視圖的排版方式將垂直翻轉(zhuǎn),如ios中诡必,某layer的geometryFlipped屬性設(shè)置為YES奢方,那么它將會(huì)相對于左下角排列
3.3.3 Z坐標(biāo)軸
和UIView不同,CALayer處于一個(gè)三維空間當(dāng)中爸舒,除了position和anchorPoint之外蟋字,還有zPosition和anchorPointZ這兩個(gè)屬性,它們都是在Z軸上描述圖層位置的浮點(diǎn)類型
zPosition主要用于在三維空間移動(dòng)和旋轉(zhuǎn)圖層扭勉,除此之外鹊奖,zPosition最實(shí)用的功能就是改變圖層的顯示順序了
我們繪制圖層時(shí),默認(rèn)都是先繪制的顯示在底層涂炎,如果希望先繪制的顯示在前面忠聚,那么可以增加zPosition的值,它就會(huì)顯示在前面了
3.4 Hit Testing
CALayer并不關(guān)心任何響應(yīng)鏈?zhǔn)录罚圆荒苤苯犹幚碛|摸事件或者手勢两蟀。但是它有一系列的方法幫你處理事件
-(BOOL)containsPoint:(CGPoint)point;
-(CALayer *)hitTest:(CGPoint)point;
containsPoint:接受一個(gè)在本土曾坐標(biāo)系下的CGPoint參數(shù),如果這個(gè)點(diǎn)在圖層的frame內(nèi)增返回就返回YES震缭,一般用于在UIView的TouchBegan方法中對圖層的坐標(biāo)進(jìn)行判斷赂毯,然后處理需要的結(jié)果
hitTest:對應(yīng)UIView中的hitTest:withEvent:方法,相對應(yīng)的,hitTest:withEvent:返回的是一個(gè)當(dāng)前視圖或者其子視圖接受觸摸事件的UIView對象党涕,hitTest:則返回圖層本身或者其子圖層對象烦感,相同的是倾鲫,如果這個(gè)點(diǎn)在圖層范圍之外欧引,則返回nil,這兩個(gè)方法都可以直接調(diào)用耿导,也可以重寫骑祟,在不同情境下使用以滿足不同的需求
注意:-hitTest:方法的測算順序嚴(yán)格依賴于圖層樹當(dāng)中的圖層順序(和UIView處理事件類似),之前提到的zPosition屬性可以改變屏幕上圖層的顯示順序气笙,但不能改變事件傳遞的順序次企。這意味著吐過改變了圖層的z軸順序,你會(huì)發(fā)現(xiàn)將不能檢測到最前方的視圖點(diǎn)擊事件潜圃,這是因?yàn)楸涣硪粋€(gè)圖層遮蓋住了缸棵,雖然他的zPosition值嬌小,但是在圖層樹中的順序靠前谭期。
3.5自動(dòng)布局
UIView中堵第,可以使用UIViewAutoresizingMask或者AutoLayout來實(shí)現(xiàn)自動(dòng)布局.
在Mac OS平臺(tái),CALayer有一個(gè)叫做layoutManager的屬性可以通過CALayoutManager協(xié)議和CAConstraintLayoutManager類來實(shí)現(xiàn)自動(dòng)排版隧出,但是它們在ios上并不適用
如果希望手工操作CALayer的布局踏志,在ios中只能使用CALayerDelegate的函數(shù):
-(void)layoutSubLayersOfLayer:(CALayer *)layer.
當(dāng)圖層的bounds發(fā)生改變,或者圖層的-setNeedsLayout方法被調(diào)用的時(shí)候胀瞪,這個(gè)函數(shù)將會(huì)被執(zhí)行针余。這使得你可以手動(dòng)地重新擺放或者重新調(diào)整子圖層的大小,但是不能像UIView的autoresizingMask好Constraints屬性可以做到自適應(yīng)屏幕旋轉(zhuǎn)凄诞。
這也是為什么最好使用視圖而不是單獨(dú)的圖層來構(gòu)建應(yīng)用程序的另一個(gè)重要原因之一圆雁。