SwiftUI 爲我們提供了許多有價值的方法來控制視圖的對齊方式,我將逐一介紹這些方法,以便您可以看到它們的實際操作。
- 最簡單的對齊選項是使用
frame()
修飾符的alignment
參數。
請記住,文本視圖總是使用顯示其文本所需的精確寬度和高度,但是當我們在其周圍放置邊框時,它可以是任何大小。由於父對象對子對象的最終大小沒有發言權,因此這樣的代碼將創建一個300x300的框架,並在其內部以較小的文本視圖爲中心:
Text("Live long and prosper")
.frame(width: 300, height: 300)
如果不希望文本居中,請使用frame()
的alignment
參數。例如,當在從左到右的環境中運行時,此代碼將視圖放在左上角
.frame(width: 300, height: 300, alignment: .topLeading)
然後可以使用offset(x:y:)
在 frame 內移動文本。
- 下一個選項是使用堆棧的對齊參數。
例如,這裏有四個大小不同的文本視圖排列在HStack
中:
HStack {
Text("Live")
.font(.caption)
Text("long")
Text("and")
.font(.title)
Text("prosper")
.font(.largeTitle)
}
我們沒有指定對齊方式,因此默認情況下它們將居中。這看起來不太好,所以您可能會考慮將它們全部對齊到一個邊,以獲得更整潔的線條,如下所示:
HStack(alignment: .bottom) {
然而,這看起來也很糟糕:因爲每個文本視圖的大小不同,它們也有不同的基線——這就是“abcde”之類的字母在一行上的名稱,這不包括行下方的字母,如“gjpy”。因此,小文本的底部低於較大文本的底部。
幸運的是,SwiftUI有兩個特殊的對齊方式,可以在第一個子級或最後一個子級的基線上對齊文本。這將導致堆棧中的所有視圖在一個統一基線上對齊,而不管它們的字體是什麼:
HStack(alignment: .lastTextBaseline) {
接下來,爲了實現更細粒度的控制,我們可以爲每個單獨的視圖定製“對齊”的含義。爲了更好地瞭解這是如何工作的,我們將從以下代碼開始:
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Hello, world!")
Text("This is a longer line of text")
}
.background(Color.red)
.frame(width: 400, height: 400)
.background(Color.blue)
}
}
運行時,您將看到VStack
緊緊圍繞着兩個文本視圖,背景爲紅色。兩個文本視圖的長度不同,但由於我們使用了.leading
對齊方式,因此在從左到右的環境中,它們都將與它們的左邊緣對齊。除此之外還有一個藍色背景的大框架。因爲frame大於VStack
,所以以VStack
中間爲中心。
現在,當VStack
開始對齊這些文本視圖時,它要求它們提供它們的 leading。默認情況下,這很明顯:它使用視圖的左邊緣或右邊緣,具體取決於系統語言。但是如果我們想改變這一點呢?如果我們想讓一個視圖具有自定義對齊方式呢?
SwiftUI爲此提供了alignmentGuide()
修飾符。這需要兩個參數:我們要更改的指南和返回新對齊方式的閉包。閉包被賦予一個ViewDimensions
對象,該對象包含其視圖的寬度和高度,以及讀取其各種邊的能力。
默認情況下,視圖的.leading
對齊嚮導是其.alignmentGuide(.leading)
——我知道這聽起來很明顯,但實際上它相當於:
VStack(alignment: .leading) {
Text("Hello, world!")
.alignmentGuide(.leading) { d in d[.leading] }
Text("This is a longer line of text")
}
我們可以重寫該對齊嚮導,以使用視圖的 trailing 作爲其leading gaide 對齊嚮導,如下所示:
VStack(alignment: .leading) {
Text("Hello, world!")
.alignmentGuide(.leading) { d in d[.trailing] }
Text("This is a longer line of text")
}
現在您將看到我爲什麼要添加顏色:第一個文本視圖將向左移動,以便它的右邊緣位於下面視圖的左邊緣的正上方,
VStack
將展開以包含它,整個內容仍將位於藍色框架的中心。
此結果與使用offset()
修飾符不同:如果偏移文本,則其原始尺寸實際上不會更改,即使生成的視圖在不同的位置呈現。如果我們偏移了第一個文本視圖而不是改變它的對齊指南,VStack
不會擴展到包含它。
雖然對齊導向閉包已傳遞給視圖的尺寸,但如果不想使用,則不需要使用它們–可以發回硬編碼的編號,或創建其他計算。例如,通過將10個文本視圖的位置乘以-10,可以爲10個文本視圖創建一個分層效果:
var body: some View {
VStack(alignment: .leading) {
ForEach(0..<10) { position in
Text("Number \(position)")
.alignmentGuide(.leading) { _ in CGFloat(position) * -10 }
}
}
.background(Color.red)
.frame(width: 400, height: 400)
.background(Color.blue)
}
要完全控制對齊指南,您需要創建自定義對齊指南。我認爲這本書應該有一個小章節…