研究 UIView 的 frame, bounds, center
Frame、Center 和 Bounds
每一個 View 或是子類別,都會擁有 Frame、Bounds、Center 屬性。
下圖透過在 UIImageView 中顯示一張圖片,並以 UIImageView 來說明這三個屬性。
iOS UIKit 的座標系方向
UIKit 的座標原點為 (0, 0) 座落於最左上角。
- 水平向右延伸的是 X 軸。
- 垂直向下延伸的是 Y 軸。
視圖的階層關係
說明 Frame、Bounds、Center 之前,首先是確立視圖之間的階層關係。
- 綠色視圖是藍色視圖的父視圖 (superview)
- 藍色視圖是綠色視圖的子視圖 (subview)
也就是說,綠色視圖的空間中,存在著藍色視圖。
Bounds 屬性
我們可以透過 Bounds 屬性,來描述視圖自己內部的座標系。
一般來說,我們熟悉的是矩型左上角的頂點座標為 (0, 0) ,接著只要確定矩型的尺寸後,就可以快速的計算出四個頂點的座標。
綠色矩型描述了這個視圖內部擁有的座標系和其尺寸,也就是視圖的 bounds 屬性。
Bounds 的矩型左上角的頂點座標為 (0, 0)。
Bounds 的尺寸大小為寬 4,高 6。
let origin = CGPoint(x: 0, y: 0)let size = CGSize(width: 4, height: 6)greenView.bounds = CGRect(origin: origin, size: size)
這時候,我們在裡面放上一個藍色方塊。
透過綠色視圖的 bounds 屬性中的 origin 座標,可以推算出藍色方塊的左上角的頂點座標,在綠色視圖的座標系中的座標為 (1, 1)。
這時候,若是我們改變綠色視圖的 bounds 屬性中的 origin 座標從 (0, 0) 變成 (-1 , -1),而尺寸大小維持不變,結果就會是下面的圖。
let origin = CGPoint(x: -1, y: -1)let size = CGSize(width: 4, height: 6)greenView.bounds = CGRect(origin: origin, size: size)
以結果來說,藍色方塊在綠色是圖中的坐標系的位置並沒有變化,依舊是座落在 (1, 1) 。
接下來我們將背景的格子移除後,從人類的視覺看起來,origin 座標從 (0, 0) 變成 (-1 , -1),使得藍色方塊向右下移動了一格。
也就是說,我們透過了指定綠色視圖的 bounds 屬性中的 origin 的值,改變了綠色視圖內的座標系的參考(綠色視圖左上角的頂點座標)。
但是對於藍色方塊來說,它永遠座落在綠色視圖座標系中的 (1, 1) 位置。
關於 bounds 屬性有趣的地方是,無論我們怎麼將綠色視圖旋轉,都不會改變綠色視圖內的座標系。
就好像雖然地球(綠色視圖)一直旋轉,但我們(藍色方塊)站的位置依舊是屬於地球(綠色視圖)的座標系。
因此我們(藍色方塊)的位置和樣貌對於同樣都是站在地球(綠色視圖)的人來說都是不變的。
不過從火星(螢幕前的你)上看,就會是我們在旋轉的樣子。
Frame 和 Center 屬性
我們可以透過 Frame 屬性描述視圖在綠色視圖(父視圖)座標系中的位置和尺寸。
藍色方塊也就是藍色視圖,可以發現它在綠色視圖的座標系中,其左上角頂點座標為 (1, 1),尺寸大小為寬等於 1,高等於 1。
這段關於藍色視圖在綠色視圖的座標系中的描述,就是藍色視圖的 Frame 屬性。
用程式碼來表達:
let origin = CGPoint(x: 1, y: 1)let size = CGSize(width: 1, height: 1)blueView.frame = CGRect(origin: origin, size: size)greenView.addSubview(blueView)
如果我們設定好藍色視圖在綠色視圖中的座標和尺寸大小,就可以從藍色視圖中的 Center 屬性得到一個座標。
這個座標就是藍色視圖的中心位置。這個位置同樣也是以綠色視圖的座標系為參考座標系。
因此藍色視圖 center 屬性的座標值就是 (1.5, 1.5)。
UIView 的 transform 屬性
最後的一個實驗是,透過 transform 屬性讓視圖旋轉,並觀察視圖的 Frame、Bounds、Center 屬性的變化。
灰色背景表示的是圖片視圖的 Frame 的位置和大小。