研究 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)

也就是說,綠色視圖的空間中,存在著藍色視圖。

視圖的座標系

每一個視圖的內部都有著屬於自己的座標系。透過矩型描述(抽象化)這樣的座標系概念。

視圖透過自己的矩型左上角的頂點座標,定為座標系起始參考點。

接著順著 X 、Y 軸延伸確定了視圖的尺寸大小。

這個矩型的概念由 CGRect 類別來表達,其中

  • origin 屬性, 指定了矩型左上角的頂點座標。
  • size 屬性,指定了矩型的尺寸大小。

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 的位置和大小。

--

--

qedqed6
彼得潘的 Swift iOS / Flutter App 開發教室

吾乃阿克西斯教教義信奉者!汝,勿要忍耐。想喝的時候就喝,想吃的時候就吃便好。因為明天並不見得還能吃得到。