Frame
UIView 的 frame 屬性本質是 CGRect 類型,它是 view 相對于其 superview 中的位置,也就是說它的位置是在 superview 的坐標系中確定的。默認情況下,superview 的坐標系中原點是在左上角處,X 軸沿原點向右延伸,Y 軸沿原點向下延伸。
如果你在.xib 文件中或者在 storyborad 中改變或重置 view 的 frame,將會很直觀地看到。如果你是通過代碼創建的 view,當你把這個 view 給 superview 的時候,這個 view 的位置將會置于它的 superview 的涵蓋范圍內。UIView 有指定的初始化方法
init(frame: CGRect)
你需要通過這個方法來給 view 設置frame ,否則 frame 的默認值將會是 CGRectZero 。
需要注意的是,如果你創建了一個 view 卻沒有將它添加給 superview ,那這個view將不會顯示出來,雖然這個道理很簡單,但我還是會在不經意之間犯這種低級錯誤,然后找半天原因。
有些 view 會有一個 standard size 比如 UIBUtton 他有一個 title ,button 的大小與其 title 有關,這時你可以通過sizeToFit
方法來自適應 button 的大小
Bounds & Center
Bounds
UIView 還有一個 bounds 屬性,該屬性也是CGRect類型,它所描述的是 view 相對于自己坐標系中的位置。
比如你想讓一個綠色的 view 在一個紅色的 view 里面,并且綠色 view 距紅色 view 的上下左右均為 10 個 points 。這時你可能會使用insetBy
方法:
v1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1)
let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10))
v2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1)
self.view.addSubview(v1)
v1.addSubview(v2)
這種用法是很常見的,當你將一個view置于另一個view中時,你需要使用view的bounds而不是frame,因為這個view需要相對于自己的坐標系來確定位置,如果你使用frame則會出現下圖的效果
如果你改變了一個view的bounds它的frame也會跟著改變,但frame變化它的中心點是不會改變的。
v2.bounds.size.height += 20
v2.bounds.size.width += 20
給綠色的視圖長寬分別加20,則它的大小將會和紅色的一樣大,完完全全的覆蓋在紅色視圖上面,呈現給用戶的就是一個綠色的視圖。但綠色視圖的 center 的確時沒有任何變化
當你創建一個 view 的時候,它的 bounds 的坐標系原點是(0,0,0,0)在自己的左上角位置。當你改變 bounds 的origin
時,你將會移動它內部的坐標系。因為 subview 在布局的時候會關心 superview 的坐標系,因此如果你改變了superview 的`bounds.origin`則將會改邊它的subview的位置,比如:
v1.bounds.origin.x += 10
v1.bounds.origin.y += 10
可以發現你改變了 bounds 的 origin ,不會改變 superview 的大小和位置,而 subview 會移動到 superview 的左上角。這是因為把 superview 以前的原點(0,0)替換成了現在的(10,10),而 subview 的 frame 并咩有發生變化,因此就會像圖上顯示的那樣,紅色 view 和 綠色 view 的左上角重合,大家可以參照下面的圖理解一下??
Center
center 其實就是一個 CGPoint 類型的點,它用來描述子視圖和父視圖之間的位置關系。
所以當你改變 view 的 bounds 是不會改變它的 center ,反之亦然,當你改變 center 時 bounds 也是不會改變的。所以view 的 bounds 和 center 之間是沒有交集的。
事實上,frame 這個屬性只是方便的描述了 center 和 bounds 的值,你可以在任何地方使用這個屬性。當你第一次創建一個 view 的時候,你需要使用指定的初始化方法init(frame:)
,你可以改變frame的值,那bounds 和 center 將會隨之改變,你改變bounds 或 center 的值,那 frame 也會隨之改變。但是,最好還是使用 bounds 和 center 來給 view 設置 它在 父視圖中 大小和位置, 而不是使用 frame。
每一個 view 都有一個自己的坐標系來表示自己的bounds, 并且每一個坐標系和他的父視圖的坐標系通過 center 可以清晰的表示出來。之前的文章有說過所有的 view 都通過一個 window 來容納,因此可以 window 中任意兩個 view 的坐標系相互轉換。 通過以下方法:
convertPoint:fromView:, convertPoint:toView:
convertRect:fromView:, convertRect:toView:
如果 toView 的參數為 nil ,則會用window替換
好了今天就到這里,明天繼續,若有紕漏歡迎指正,共同進步??