在上一節(jié)中,看到當(dāng)沒有加入任何限制時闸迷,HStack是如何分配空間給自己的子元素的烘苹,通過迭代依次進行。在本節(jié)中坝茎,將講解.layoutPriority
和.frame
這兩個modifier是如何影響布局結(jié)果的涤姊。
布局優(yōu)先級修飾符.layoutPriority
繼續(xù)使用上一節(jié)中的例子,使用HStack依次平鋪三個Text嗤放,下面的示例代碼中思喊,沒有任何的優(yōu)先級區(qū)別,采用默認(rèn)的方式進行布局次酌。
struct DemoView: View {
var body: some View {
HStack {
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}.background(Color.yellow)
}
}
那么.layoutPriority
這個modifier是什么呢恨课?先來看一下官方文檔的解釋:
Sets the priority by which a parent layout should apportion space to the child.
The default priority is 0. In a group of sibling views, raising a view’s layout priority encourages that view to shrink later when the group is shrunk and stretch sooner when the group is stretched.
A parent layout should offer children with the highest layout priority all the space offered to the parent minus the minimum space required for all its lower-priority children, and so on for each lower priority value.
提煉一下重點:
- 當(dāng)沒有使用該modifier時,默認(rèn)值為0岳服;
- 回想一下上一節(jié)中的布局迭代的順序剂公,父視圖在挑選子元素布局的順序,依賴于該modifier的大小吊宋,modifier值越大纲辽,優(yōu)先級越高;
- 取得最高優(yōu)先級的元素后璃搜,該子元素可用于布局的空間是父視圖空間減去剩下元素個數(shù)乘以一個
minimum space
拖吼,再減去子元素間的默認(rèn)間隔(這個默認(rèn)間隔可以通過Stack的初始化函數(shù)進行修改)后的大小,這個minimum space
在之后的實例中可以看到这吻。
修改一下之前的示例代碼吊档,添加.layoutPriority
struct DemoView: View {
var body: some View {
HStack {
Text("A great and warm welcome to Kuchi")
.layoutPriority(-1)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.layoutPriority(1)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}.background(Color.yellow)
}
}
它們的優(yōu)先級分別為-1,1唾糯,0怠硼。最后一個Text由于沒有給它設(shè)置優(yōu)先級鬼贱,所以它的優(yōu)先級為默認(rèn)值0,得到的結(jié)果如下圖所示:
從這個結(jié)果中香璃,可以看到第一個Text由于優(yōu)先級最低-1这难,被壓縮成了一個細(xì)條,這個細(xì)條的寬度就是上面解釋中所說的
minimum space
增显,兩個Text中間的間隔就是一個默認(rèn)間隔雁佳。
小結(jié)
當(dāng)設(shè)置了優(yōu)先級以后,布局的過程便和上一節(jié)中所說的有所不同了同云,總結(jié)如下:
- 父視圖給出了可用于布局(可以自己支配)的frame糖权;
- 當(dāng)有多個子視圖時,在子視圖中進行挑選找出優(yōu)先級最高的炸站,選擇第一個子視圖星澳。
- 對第二步找到的子視圖進行布局,把自己的可支配的大小減去剩下元素個數(shù)乘以
minimum space
旱易,再減去子元素間的間隔禁偎,將這一部分空間分配給該視圖進行布局- 子視圖基于父視圖提供的frame來看看自己到底占據(jù)的大小
- 子視圖算好之后,父視圖會減去這個子視圖所占據(jù)的size阀坏,把剩下的部分分配給其余的子視圖如暖,回到步驟2,進行下一次循環(huán)忌堂,直到所有子視圖繪制完成盒至。
- 當(dāng)所有子視圖繪制結(jié)束后,父視圖再根據(jù)子視圖所占據(jù)空間來調(diào)整自己的size
當(dāng)有多個子視圖具有相同優(yōu)先級時士修,第三步的計算方式將優(yōu)先不同:
對第二步找到的子視圖進行布局枷遂,把自己的可支配的大小減去剩下低優(yōu)先級元素個數(shù)乘以
minimum space
,再減去子元素間的間隔棋嘲,將這一部分空間均分給和當(dāng)前視圖具有相同優(yōu)先級的元素酒唉,而這個元素所占面積為其中一份。
Tips: 如果對于這種布局結(jié)果有疑問沸移,比如為何第一個和第二個Text所占的空間為什么會不相同痪伦,請查閱上一節(jié)。
frame修飾符
那么再來看看frame修飾符雹锣,frame具有最高的優(yōu)先級流妻,布局時,會優(yōu)先為有frame的子視圖進行布局笆制,示例代碼如下:
struct DemoView: View {
var body: some View {
HStack {
Text("A great and warm welcome to Kuchi")
.frame(width: 200, height: 200)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.layoutPriority(1)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}.background(Color.yellow)
}
}
frame是最好理解的布局修飾符,尤其對應(yīng)熟悉UIKit的同學(xué)涣达,在這里也就無需多介紹了在辆。了解了視圖的布局后证薇,其實會發(fā)現(xiàn),在平時的開發(fā)過程中匆篓,他們的使用場景其實并不多浑度,通常情況下,都會給出固定的位置鸦概,來放置元素箩张。只有當(dāng)我們需要類似自動填充的流式布局時,才需要了解并掌握這些布局的原理窗市。
題外話
在之前的講解中說到了布局中先慷,兩個相鄰子元素的默認(rèn)間隔,這個間隔可以通過構(gòu)造函數(shù)進行修改:
@inlinable public init(alignment: VerticalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: () -> Content)
它的第二個參數(shù)spacing就是間隔咨察,默認(rèn)值為nil论熙,也就是默認(rèn)間隔∩阌可以通過將其設(shè)置為0脓诡,來取消這個間隔。