從 CALayer 的 Position、AnchorPoint 說起

Natai發表於2019-04-17

本文 demo 地址

有的東西雖然基礎,但是耐不住人老記性差呀,自己寫下來好過次次再搜咯,so......

AnchorPoint 和 Position

AnchorPoint

anchorPoint直譯過來就是錨點,layer 以該點為基準進行各種 transform 變換,其值從 (0, 0) 到 (1, 1),預設值為 (0.5, 0.5)。該屬性的文件中提到:

'(0, 0)' is the bottom left corner of the bounds rect, '(1, 1)' is the top right corner

這裡的說的左下角,是在以螢幕的左上角為原點的座標系中。而在我們日常生活的座標系中,原點在螢幕的左下角,那麼 (0, 0) 位置則是左上角。

Position

實際表示的是錨點在superLayer中的位置。

兩者的聯絡

單獨修anchorPointposition可以修改掉 layer 的位置,但是並不會對另一個屬性造成影響。下面例子中,藍色檢視的frame.size = (100.0, 100.0),有一個frame.size = (0, 0, 100.0, 100.0)的黃色子檢視。

單獨修改anchorPoint

修改錨點
修改錨點

修改錨點前後的輸出
修改錨點前後的輸出

單獨修改position

修改position
修改position

修改position前後的輸出
修改position前後的輸出

從以上的輸出可以看出,單獨修改這兩個屬性,發生改變的其實是黃色檢視的frame.origin。不難得到規律:

frame.origin.x = position.x - anchorPoint.x * bounds.size.width
frame.origin.y = position.y - anchorPoint.y * bounds.size.height 
複製程式碼

如果想要修改錨點後,origin位置不發生變化,根據以上公式,則需要相應的修改position,或者直接暴力的修改origin的值。

CALayer 和 UIView 的位置、大小

其實 view 的frameboundscenter都是直接返回了 layer 的frameboundsposition屬性。

Frame 和 Bounds

不管frame還是bounds,都需要一個參考座標系。frame參考的是父檢視的座標系,表示在父檢視座標系中的位置和大小;bounds參考的是自身檢視的座標系,表示在自身檢視座標系中的位置和大小。

Bounds

藍色檢視 A 的frame.size = (100.0, 100.0) ,有一個frame.size = (0, 0, 100.0, 100.0)的黃色子檢視 B。在修改 Abounds = (-20, -20, 100.0, 100.0)的時候,如圖:

修改bounds
修改bounds

A 的位置不變,B 的位置往右下偏移。因為 A 的origin在其自身座標系中的位置變為了 (-20, -20),B 的frame.origin還是 (0, 0),表示 B 在 A 的座標系中位置為 (0, 0),那麼 B 的左上角就相對於 A 的左上角向右下各偏移了 20。

UIScrollView 的 contentOffset

初識 UIScrollView 的時候,我以為在拖動它時,是通過修改子檢視的frame來產生位移效果的。其實思考一下就會得到子檢視位移距離的規律:

translocation.x = subView.frame.origin.x - superview.bounds.origin.x
translocation.y = subView.frame.origin.y - superview.bounds.origin.y
複製程式碼

剛好 scrollView 的原理其實是修改了自身的bounds,而不是修改子檢視的frame

不巧的是,contentOffsetbounds的值又是一模一樣的,我們可以理解為它只是bounds屬性的一個殼。本文的 demo 中就用了一個 tableView 滾動時輸出兩個屬性證明了以上的幾個說法。

相關文章