SwiftUI 沒有Autolayout

戴萌
6 min readApr 4, 2022

UIKit 的UI 部署主要會用二種方式,1是Frame,2是Autolayout,一開始在iPhone尺寸不多的時期,大家都喜歡直接使用Frame 來指定元件位置和大小,後來Apple 推出來Autolayout 是可以讓元件依據Constraint來決定元件位置與大小,Autolayout 其實不是很好學習,但是會了之後就很好用。

SwiftUI 的UI 部署與 UIKit 完全不同,SwiftUI 有專用的排版元件,也就是ZStack, VStack, HStack,對View 調整需要透過 Modifier,像是 .frame, .opacity, .foregroundColor …等等,不過在SwiftUI 上使用Modifier 來調整View,實際上SwiftUI會重新繪製一個View,與排版相關的 Modifier 主要會用到 .padding / .frame

若元件是在 Stack 裡面的話,可以使用Spacer來調整元件位置

.frame

主要是用來設定Size及Alignment

frame 除了可以像之前一樣設定Width/Height外,在使用的時候會發現 frame 有幾個沒看過的參數 minWidth, idealWidth, maxWidth, minHeight, idealHeight, maxHeight,來介紹一下它們的

minWidth, maxWidth 就如果它們的名字,可以指定最大或最小寬度

minHeight, maxHeight 就是可以指定最大或最小高度

例如

HStack {
Text("Hello, world!")
}
.frame(maxWidth: 50)
HStack {
Text("Hello, world!")
}
.frame(maxHeight: 50)

idealWidth/idealHeight 是最適寬高,這二個參數我個人是不太會使用,多數情況 minWidth, maxWidth, minHeight, maxHeight 都可以解決,因此無法確定這二個參數的使用時機

若是希望 minWidth, maxWidth, minHeight, maxHeight 可以與螢幕同寬高,可以這樣寫

.frame(maxWidth: .infinity, maxHeight: .infinity) 最大寬高與螢幕相同
.frame(maxWidth: .infinity) 最大寬與螢幕同寬
.frame(maxHeight: .infinity) 最大高與螢幕同高

.padding

就如同它的名字,是用來設定View 與 View 的間距的,可以設定上(top)、下(bottom)、左(left)、右(right)、水平(horizontal)、垂直(vertical)

.padding() 表示 .padding(.all),padding 是有預設值的記得可好像是 17pt
.padding(.horizontal, 20) ,是指左右都間隔20pt

.padding 相對 .frame 比就較單純,使用個幾次就可以知道它的操作,雖然一開始會不太習慣,但習慣之後就很好用了

Text("Hello, world!")
.padding()
Text("Hello, world!")
.padding(.bottom, 40)

Spacer

Spacer 就是個神奇框框,若只是寫 Spacer() 它會把剩下的空間都占滿,但如果不想要占滿全部的空間,也可以用 .frame 給它寬高,這個function 的使用情境就非常多種,例如

HStack {
Spacer()
Text("Hello, world!")
Spacer()
}
HStack {
Spacer()
Text("Hello, world!")
}
HStack {
Text("Hello, world!")
Spacer()
}

有一點要特別注意的,因為 Spacer 是有預設值的,所以當你的元件多到在某些尺寸下可能比 Spacer 的預設值小的時候,View 的寬度是會被擠出螢幕可視範圍

那…要怎麼辨呢?

這時候就要用到 Spacer 的參數 minLength 就如它的名字,可以設定 Spacer 最小範圍

Spacer(minLength: 0)

minLength 設為 0 ,這樣當元件多的時候,View 的寬度就不會因為 Spacer預設值而被擠出可視範圍

SwiftUI 的畫面部署的方式與過去UIKit的可說是完全不同,雖然後期的UIKit 也是有 Stack 可以使用,還是有些許的不同,因此在看到UI 設計圖的時候,第一個要想的就變成了「這需要用那個Stack?、需要幾個Stack?」之後才會去想要用那個元件、 要不要用 Spacer ? 、.frame.padding 要怎麼設定,與UIKit 的思考順序不太一樣,一開始一定會非常不習慣,在使用一陣子之後,反而會覺得比UIKit時期簡單很多!!

最後祝大家開發愉快!!

--

--