Swift — 說說 Frame & Bounds

解讀 Frame 與 Bounds 的差別。

Jeremy Xue
5 min readJul 14, 2018

前言:

在設定一個元件的寬高及位置的時候,常常會需要動用到這兩個屬性。但是常常會讓人搞不清楚兩者之間的差異,因為自己在新手階段和製作動畫的時候常常需要調整到這兩個屬性,有時總會手忙腳亂。

所以我想利用這次教學來幫大深入一下 Frame 與 Bounds 的差別。

導覽 — 蘋果官方文檔:

# Frame

用於描述於 父視圖座標系 中視圖的位置及大小。

此矩形在其父視圖的座標系定義視圖的大小與位置。在佈局操作期間用於此矩形設置視圖的大小及位置,設置這個屬性會更改 center 屬性指定的點並且相對應的更改 bounds 矩形中的大小。

警告:如果 變形 屬性不是 identity 的變形效果,那麼此屬性值未定義,因此應該被忽略。

改變 frame 矩形會自動重新顯示視圖,而不需調用其 draw(_:) 方法。如果希望 UIKit 在 frame 矩形改變時調用 draw(_:) 方法,請將 contentMode 屬性設置為 UIView.ContentMode.redraw。

更改這個屬性可以被設置動畫。但是,如果 transform 屬性包含非識別的變形,則 frame 屬性的值是未定義的,不應該被修改。在這種情況下,使用 center 屬性重新定位視圖,並使用 bounds 屬性調整大小。

# Bounds

用於描述試圖在 自身座標系 中的位置及大小。

默認 bounds 原點是 (0,0),其大小與 frame 屬性中矩形的大小相同。更改此矩形的大小部分會相對於其中心點增大或縮小視圖。更改大小還會更改 frame 屬性中相匹配的矩形大小。其 Bounds 矩形的座標點總是被指定。

改變 frame 矩形會自動重新顯示視圖,而不需調用其 draw(_:) 方法。如果希望 UIKit 在 frame 矩形改變時調用 draw(_:) 方法,請將 contentMode 屬性設置為 UIView.ContentMode.redraw。

更改這個屬性可以被設置動畫。

# 圖解

我相信大家看了蘋果官方的文件導讀後,應該還只是略懂略懂。接下來,我們接下來用畫面表達這兩者之間的差別與應用。

frame 與 bounds 測試範例圖

# X、Y 位置與寬高

接著我們將這些視圖與程式碼做連結,之後印出這些視圖的 frame 與 bounds 來看一下結果:

各個視圖的 frame 和 bounds 的 (x, y)座標及寬高

你會看到這些的 frame 都是由其 superView 上的座標來決定它,最明顯的是可以由藍色視圖的 frame 座標為: (0,0) 看出來。原因是藍色視圖在紅色視圖的左上角,並且紅色視圖為藍色視圖 superView,因此藍色視圖的 frame 座標為: (0,0)。其他的視圖的座標位置也是根據這樣決定。

而這些視圖的 bounds 都是由自身座標位置決定的,所以他們的座標位置都為 (0,0),frame 與 bounds 兩者寬高都會相同,就算視圖改變了寬高,兩者依然會是相匹配的寬高。

# 中心點位置

使用 center 與 bounds.max 求中心點位置

通常我們可以使用 center 這個屬性來查看該視圖的中心點,但是這個 center 也是透過設置 frame 而產生出來的,所以它也是表示在其 superView 上的中心點位置,所以你看到我們灰色區域寬高為 300,那麼紅色區域的 center 位置就為( 150,150);紅色區域寬高為 200,那麼藍色區域的 center 位置就為( 100,100)。

所以當我們要設定加到其中某個視圖的中央時,我們應該使用其 bounds 的 maxX 與 maxY,將兩者除以 2,或是使用 midX、midY,便能得出我們該視圖的中心點位置。

frame.max 與 bounds.max 差別

注意!這邊不能直接使用 frame.maxX 和 frame.maxY,因為它是由該視圖的 superView 的 x、y 軸開始算起。若要使用,則需要將 maxX 減去 minX ,Y 軸也是如此。

練習:

讓我們試著不用 Storyboard 方式來畫出上面的台灣國旗吧 🇹🇼( Taiwan No.1

因為我很懶惰,所以我寫了一個 functions 來創建我們的 View:

接下來我們就可以在 viewDidLoad 套用此方法來製作 View 了:

後記

大家練習的結果應該就跟上面 StoryBoard 的圖案是一樣的,如果錯誤的話要檢查一下屬性是否設定錯誤了,希望到大家能透過這次的了解到 frame 和 bounds 兩者之間的差距。

附上這一次的小 Demo,感謝收看:

--

--

Jeremy Xue

Hi, I’m Jeremy. [好想工作室 — iOS Developer]