布局
在uiview中與位置,尺寸有關的屬性有 frame
bounds
center
在此不多贅述,在calayer中同樣有與其相對應的屬性 frame
bounds
position
需要注意的是 center
與position
雖然字面表達不一樣,但是其功能是一致的,為了更加清晰的展示以上內容,我在故事板中創建一個有色uiview.
圖片一
在控制臺打印日志:
1
2
3
4
5
6
|
customview_frame:{{117, 241}, {140, 185}} customview_bounds:{{0, 0}, {140, 185}} customview_center:{187, 333.5} customview_layer_frame:{{117, 241}, {140, 185}} customview_layer_bounds:{{0, 0}, {140, 185}} customview_layer_position:{187, 333.5} |
根據日志所打印內容可知 uiview與calayer 的布局屬性是一一對應的.
以上內容了解后我們需要直達frame本質上是一個復合的屬性,也就是說他是由bounds position transform計算得到的(transform:放大,旋轉等).為了證實這件事,我們將上面的有色view旋轉一個角度.
圖片二
在控制臺打印日志:
1
2
3
|
customview_layer_frame:{{80.128221735089298, 218.39265014993941}, {213.74355652982138, 230.21469970012117}} customview_layer_bounds:{{0, 0}, {140, 185}} customview_layer_position:{187, 333.5} |
通過對比兩次打印日志的對比不難發現,當我們將圖層旋轉后 bounds position 都沒有改變,而 frame 卻大有改變.那么問題來了,此時的 frame 代表的是什么?我們以customview_layer_frame為 frame 在視圖上添加一個新的視圖并且將其作為旋轉視圖的背景.
圖片三
圖片三與圖片二相比我們可以發現,frame實際上代表了覆蓋在圖層旋轉之后的整個軸對齊的矩形區域.
錨點-anchorpoint
錨點這個詞初識是很陌生的,好比航船的錨用來固定航船,圖層中的錨點也具有相同的功能,錨點可以 固定 圖層,也就是說錨點是圖層的句柄.默認情況下錨點位于圖層的中點,我們將圖二的的錨點打印.
customview_layer_anchorpoint:{0.5, 0.5}
我了便于觀察,我在已有的 uiview 上面添加一個同樣大小位置顯色不同的uiview(在橙色視圖上面添加一個綠色視圖,綠色視圖的錨點在綠色視圖的中心點).
圖片四
將綠色視圖的錨點設置為(0.0).
綠色視圖的錨點在綠色視圖的左上角.
圖片五
再做一次實現,我將綠色視圖的錨點設置為(1,1).也就是將錨點設置在綠色視圖的右下角.
圖片六
改變錨點可以蓋面綠色視圖的展示效果,那么此時的 bounds
position
frame
呢?我在控制臺打印錨點為(0.5,0.5)與(1,1)時的數據.
1
2
3
4
|
//(0.5,0.5) customview_layer_frame:{{0, 0}, {140, 185}} customview_layer_bounds:{{0, 0}, {140, 185}} customview_layer_position:{70, 92.5} |
1
2
3
4
|
//(1,1) customview_layer_frame:{{-70, -92.5}, {140, 185}} customview_layer_bounds:{{0, 0}, {140, 185}} customview_layer_position:{70, 92.5} |
由兩個數據對比可得,錨點的改變只會改變 frame
.
到此錨點的基本概念已經基本了解,那么錨點用在什么地方呢?在這我列舉一個簡單的用法.現在我將錨點為(0.5,0.5)與(1,1)的綠色視圖分別進行旋轉(持續).
圖片七
圖片八
對比兩個gif,可以知道視圖的旋轉是以錨點為中心進行旋轉的.
坐標系
坐標系無非就是(x,y,z),我不對(x,y)進行講解,著重講解一下z.在視圖坐標系中,z軸與我們在數學中的z軸是有相同的效果的,他表現的是垂直的坐標,如果我們為圖層設置z軸坐標該圖層將會在未設置z軸坐標或者小于該z軸坐標的圖層上方展示.為了著重表現該現象,我在綠色視圖中添加一個藍色圖層與紅色圖層,先看一下代碼清單.
1
2
3
4
5
6
7
8
|
calayer * bluelayer = [[calayer alloc]init]; bluelayer.frame = self.greenview.layer.frame; bluelayer.backgroundcolor = [uicolor bluecolor].cgcolor; calayer * redlayer = [[calayer alloc]init]; redlayer.frame = self.greenview.layer.frame; redlayer.backgroundcolor = [uicolor redcolor].cgcolor; [self.greenview.layer addsublayer:bluelayer]; [self.greenview.layer addsublayer:redlayer]; |
由代碼可以發現先添加的藍色圖層后添加的紅色圖層,因此紅色圖層在最上方.
圖片九
將藍色的圖層的z軸坐標設置為1.0f.
圖片十
hit testing
calayer 是不關心響應鏈事件的,但是它提供了兩個方法來處理事件.
- -containspoint:
- -hittest:
-containspoint: 接受一個在本圖層坐標系下的cgpoint,如果這個點在圖層frame范圍內就返回yes,否則返回no.為了理解這一性質我寫一個小案例,在以后的藍色圖層和白色圖層中點擊,如果點擊藍色區域控制臺打印blue,如果在白色區域控制臺打印white.
1
2
3
4
5
6
7
8
9
|
- ( void )touchesbegan:(nsset<uitouch *> *)touches withevent:(uievent *)event { cgpoint point = [[touches anyobject]locationinview:self.view]; point = [self.bluelayer convertpoint:point fromlayer:self.view.layer]; if ([self.bluelayer containspoint:point]) { nslog(@ "blue" ); } else { nslog(@ "white" ); } } |
-hittest: 也是接受一個 cgpoint 但是返回的是 calayer,通過判斷返回的圖層是否是所要響應的圖層然后做出相應的操作,繼續上面的案例稍加改動.
1
2
3
4
5
6
7
8
9
|
- ( void )touchesbegan:(nsset<uitouch *> *)touches withevent:(uievent *)event { cgpoint point = [[touches anyobject]locationinview:self.view]; calayer * layer = [self.view.layer hittest:point]; if (layer == self.bluelayer) { nslog(@ "blue" ); } else { nslog(@ "white" ); } } |
自動布局
當使用視圖的時候,可以充分利用uiview的uiviewautoresizingmask
和nslayoutconstraint
進行自動布局,但是如果想要隨意控制calayer
的布局,就需要通過使用 calayerdelegate
.如下函數:
- (void)layoutsublayersoflayer:(calayer *)layer;
當圖層的bounds發生改變,或者圖層的-setneedslayout
方法被調用的時候,這個函數就會執行.這時可以手動的對圖層進行重新繪制,但是不能像uiview的autoresizingmask
和constraints
屬性做到自適應屏幕旋轉.這也是為什么最好使用視圖而不是單獨的圖層來構建應用程序的重要原因之一.
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!
原文鏈接:http://www.cnblogs.com/xubaoaichiyu/p/6553859.html