1、繼承關係、遵照協議、隸屬框架及可用平臺 html
UIStackView 類提供了一個高效的接口用於平鋪一行或一列的視圖組合。Stack視圖使你依靠自動佈局的能力,建立用戶接口使得能夠動態的調整設備朝向、屏幕尺寸及任何可用範圍內的變化。Stack視圖管理着全部在它的 arrangedSubviews 屬性中的視圖的佈局。這些視圖根據它們在 arrangedSubviews 數組中的順序沿着 Stack 視圖的軸向排列。精確的佈局變量根據 Stack 視圖的 axis, distribution, alignment, spacing, 和其它屬性共同決定。 ios
使用 stack 視圖,打開一個你但願編輯的 Storyboard,從對象庫中拖拽出一個 Horizontal Stack View 或者一個 Vertical Stack View,並放置到你但願的位置上。下一步,將控件或視圖拖拽放置到 stack 中,若是須要你能夠繼續添加視圖或者控件給指定的 stack。Interface Builder 將根據 stack 的內容自動調節尺寸。你也能夠經過修改屬性面板中 Stack視圖的屬性調整 stack 內容的外觀。 數組
注意:你須要負責指定 stack 視圖的位置和尺寸(可選的)。而後 stack 視圖將管理其內容的佈局和尺寸。 安全
2、Stack 視圖與自動佈局 app
Stack 視圖使用自動佈局來定位和控制其管理的視圖的尺寸。stack 視圖沿着它的軸向拼湊第一個和最後一個被管理視圖,使其邊界平齊。對於一個水平 stack 視圖,這意味着第一個被管理視圖的左邊界是與 stack 的左邊界平齊的,而且最後一個被管理視圖右邊界與 stack的右邊界平齊。對於垂直 stack,上邊界和下邊界是各自平齊的。若是你設置了 stack 視圖的 layoutMarginsRelativeArrangement 屬性爲 YES,stack 視圖將使用相關的邊距與其內容對齊,而不是邊界。 框架
對於除去 UIStackViewDistributionFillEqually 分佈之外的分佈方式,stack 視圖使用被管理視圖的 intrinsicContentSize 屬性來計算沿着 stack 軸向的視圖尺寸。UIStackViewDistributionFillEqually 分佈將調節全部被管理視圖的在 stack 軸向上擁有相同尺寸,以填充 stack 視圖。若是可能,stack 視圖將拉伸全部被管理視圖,來匹配其在 stack 軸向上最長的原有尺寸(譯註:保證長寬比的狀況下根據 stack 軸向長度拉伸視圖)。 ide
對於除去 UIStackViewAlignmentFill 對齊方式之外的對齊方式,stack 視圖使用其管理的視圖的 intrinsicContentSize 屬性來計算視圖垂直於 stack 軸向的尺寸。 UIStackViewAlignmentFill 從新調節了全部其管理的視圖,使這些視圖填充 stack 視圖垂直於其軸向空間。若是可能,stack 視圖將拉伸其全部管理的視圖來匹配其垂直於 stack 軸向的最大固有尺寸。 佈局
3、定位和調整 Stack 視圖尺寸 動畫
當 Stack 視圖容許你佈局其內容而不直接使用自動佈局,你將仍然須要使用自動佈局來定位 stack 視圖。一般狀況下,這意味着須要拼湊至少兩個邊界相鄰的stack來定義它的位置。沒有額外約束的狀況下,系統會爲 stack 視圖計算一個尺寸來適應其內容: ui
沿着 stack 視圖軸向,其適應尺寸等於其管理的視圖尺寸與間距的和;
垂直於 stack 視圖軸向,其適應尺寸等於其管理的視圖中最大的視圖的尺寸;
若是 stack 視圖的 layoutMarginsRelativeArrangement 屬性設置爲 YES,stack 視圖的適應尺寸會包括邊距空間。
你能夠提供額外的約束來具體說明 stack 視圖的高度、寬度或者二者兼有。在這些狀況下,stack 視圖調整了其管理的視圖的佈局和尺寸來填充指定區域。精確的佈局變量根據 stack 視圖的屬性得到。能夠經過查看 UIStackViewDistribution 和 UIStackViewAlignment 枚舉,以得到一個完整的 stack 視圖在其內容空間多餘或空間不足狀況下的處理描述。
你也能夠根據 stack 視圖的第一條或最後一條基線定位它,而不是使用頂部、底部或者中心的Y值。相似於 stack 視圖的適應尺寸,這些基線都是基於 stack 視圖的內容計算獲得的。
一個水平的 stack 視圖調用 viewForFirstBaselineLayout 方法或 viewForLastBaselineLayout 方法時返回它最高的視圖。若是最高的視圖也是一個 stack 視圖,那麼其返回的將是在嵌套的 stack 視圖上調用 viewForFirstBaselineLayout 方法或 viewForLastBaselineLayout 方法的結果。
一個垂直的 stack 視圖當調用 viewForFirstBaselineLayout 方法時返回的是其管理的第一個視圖,當調用 viewForLastBaselineLayout 方法時返回的是其管理的最後一個視圖。若是這兩個視圖之一也是 stack 視圖,那麼其返回的將是在嵌套的 stack 視圖上對應調用 viewForFirstBaselineLayout 方法或 viewForLastBaselineLayout 方法的結果。
注意:基線對齊方式只做用於那些高度匹配其本來內容高度的視圖。若是視圖被拉伸或壓縮過,那麼基線將出如今錯誤的位置上。
4、通用 Stack 視圖佈局
這有一些通用方法用於 stack 視圖。這個清單是要高亮一些有用的示例來顯示 stack 視圖的靈活性。目前這還不是一個完整的清單。
只是定義位置。你能夠經過固定兩個與其父視圖相鄰的邊界來定義 stack 視圖的位置。在這裏,stack 視圖的尺寸將根據其管理的視圖在兩個維度上自由擴展。當你想要 stack 視圖的內容展示其原有內容尺寸,和你想要管理其餘與 stack 視圖有關聯的用戶接口元素時是特別有用的。
舉個例子,在 Figure 1中,stack 視圖的左邊界和上邊界都已經相對固定於其父視圖。這些標籤將根據帶有8個點的二者之間的空間做爲第一基線校準。這對於相對於其自己左對齊的 stack 視圖內容是有效的。
Figure 1.定義位置
定義沿着 stack 視圖軸向的尺寸。這裏,你固定了沿着 stack 視圖軸向相對於其父視圖的兩個邊界,定義了 stack 視圖沿着其軸向的尺寸。你將須要固定其餘邊界中的一個來定義 stack 視圖的位置。stack 視圖將沿着其軸向改變尺寸和位置來填充定義的空間;然而,未固定的邊界將根據其管理的最大視圖的尺寸自由移動。
舉例如 Figure 2,stack 視圖的左、上、右邊界都已經相對於其父視圖固定了。使用 UIStackViewDistributionFill 分佈使得其內容重設尺寸來填充它的寬度,而且從文本框有比標籤更低的內容緊湊優先級開始,它將在必要的時候被拉伸。
Figure 2.定義沿着 stack 視圖軸向的尺寸
定義垂直於 stack 視圖軸向的尺寸。這相似於上一個示例,可是你固定了垂直於 stack 視圖軸向的兩個邊界和沿着軸向的一個邊界。這使得 stack 視圖在你增長或移除其管理的視圖時將沿着其軸向擴展或回縮。除非你使用了 UIStackViewDistributionFillEqually 分佈,被管理的視圖將根據其原有尺寸調節尺寸。垂直於其軸向的視圖將根據其 stack 視圖的對其模式在其定義的範圍內平鋪。
舉例,Figure 3展現了一個包含了四個標籤和一個按鈕的垂直 stack 視圖。這個 stack 視圖使用了8個點的間隙和 UIStackViewAlignmentCenter 對齊方式。stack 視圖的高度將根據 stack 內部的元素的增減而增大或回縮。
Figure 3.定義垂直於 stack 視圖軸向的尺寸
同時定義 stack 視圖的位置和尺寸。這裏你固定了 stack 視圖的全部四個邊界。stack 視圖將在提供的範圍以內平鋪其內容。舉例,Figure 4展現了一個全部四個邊界都相對於其父視圖固定的垂直 stack 視圖。經過使用 UIStackViewAlignmentCenter 對齊方式和 UIStackViewDistributionFill 分佈方式,stack 視圖確保其內容將水平和垂直居中填充屏幕。然而,得到想要的佈局須要兩個額外的步驟。默認狀況下,stack視圖會垂直拉伸標籤而不是圖片。要縮放圖片控件,就要下降其內容緊湊優先級到低於標籤。額外的,爲了保持圖片縮放時的長寬比,你必須設置圖片視圖的模式爲 Aspect Fit。增長一個圖片視圖與 stack 視圖間寬度相等約束將有助於確保圖片將被縮放來填充可用範圍。
Figure 4.同時定義 stack 視圖的位置和尺寸
5、管理 Stack 視圖的展示
UIStackView 是 UIView 的非渲染型子類。它沒有提供其自有的任何用戶接口。相反的,它只管理被其管理的視圖的位置和尺寸。所以,有些屬性(如 backgroundColor)在 stack 視圖上是無效的。相似的,你沒法重寫 layerClass,drawRect: 或 drawLayer:inContext: 方法。
這裏有一系列的屬性來定義 stack 視圖如何平鋪其內容。
axis(軸向) 屬性決定了 stack 的朝向,只有垂直或水平;
distribution(分佈) 屬性決定了其管理的視圖在沿着其軸向上的佈局;
alignment(對齊) 屬性決定了其管理的視圖在垂直於其軸向上的佈局;
spacing(空隙) 屬性決定了其管理的視圖間的最小間隙;
baselineRelativeArrangement 屬性決定了其視圖間的垂直間隙是否根據基線測量獲得;
layoutMarginsRelativeArrangement 屬性決定了 stack 視圖平鋪其管理的視圖時是否要參照它的佈局邊距
一般狀況下,你會使用一個 stack 視圖來佈局小數量的視圖。你能夠經過在其餘 stack 視圖中嵌套多個 stack 視圖的方式建立更加複雜的視圖層次結構。舉例,Figure 5展現了一個包含兩個水平 stack 視圖的垂直 stack 視圖。每個水平 stack 視圖各包含一個標籤和一個文本框。
Figure 5.Stack 視圖的嵌套
你也能夠經過增長被管理的視圖的額外約束來完美的調節一個被管理視圖的展示。舉例說明,你可使用約束類設置視圖的最小或最大的高度或寬度。或者你能夠定義一個長寬比。當平鋪其內容時,stack 視圖將使用這些約束。舉例來講,在Figure 4中,當圖片被縮放時,圖片視圖的一個長寬比約束被強行賦予了一個長寬比常數。
注意:當給一個 stack 視圖內的視圖增長約束時要特別注意避免傳入衝突。做爲慣例,若是一個視圖的尺寸在一個指定的維度上默認回到其本來內容尺寸,那麼你能夠安全的在這個維度上增長約束。
6、維護其管理的視圖與子視圖之間的統一性
Stack 視圖確保它的 arrangedSubviews 屬性將一直是其 subviews 屬性的子集合。明確的說,stack 視圖強制實施瞭如下規定:
不管什麼時候 stack 視圖增長了一個視圖到它的 arrangedSubviews 數組,其也將把這個視圖做爲子視圖增長,若是還未增長的話。
不管什麼時候一個子視圖從 stack 視圖中被移除,那麼 stack 視圖也將將其從 arrangedSubviews 數組中移除。
從 arrangedSubviews 移除一個視圖並不會將其做爲子視圖移除。stack 視圖將再也不管理該視圖的尺寸和位置,可是該視圖仍將是視圖結構的一部分,而且當其可見的狀況下仍會被渲染到屏幕上。
當 arrangedSubviews 數組一直包含着 subviews 數組的子集合,這些數組間的順序仍然是獨立的。
arrangedSubviews 數組的順序定義了展示在 stack 中的視圖的順序。對於水平 stack 視圖,這些視圖將以閱讀順序平鋪,即較小索引的視圖在較大索引視圖的左側。對於垂直 stack 視圖,這些視圖是從上到下平鋪的,及較小索引的視圖在較大索引視圖的上方。
subviews 數組中的順序定義了子視圖在Z軸上是順序。若是視圖重疊,有較小索引的子視圖將出如今有較大索引的子視圖後方。
7、動態改變 Stack 視圖內容
當視圖被加入、移出或插入 arrangedSubviews 數組時,或當一個被管理的子視圖的 hidden 屬性改變時,stack 視圖都會自動更新它的佈局。
OC代碼以下:
1
2
3
4
|
// Appears to remove the first arranged view from the stack.
// The view is still inside the stack, it's just no longer visible, and no longer contributes to the layout.
UIView * firstView = self.stackView.arrangedSubviews[0];
firstView.hidden = YES;
|
Swift代碼以下:
1
2
3
4
|
// Appears to remove the first arranged view from the stack.
// The view is still inside the stack, it's just no longer visible, and no longer contributes to the layout.
let firstView = stackView.arrangedSubviews[0]
firstView.hidden = true
|
stack 視圖也會自動響應其任何屬性的改變。舉例,你能夠更新 stack 視圖的 axis 屬性來動態改變的朝向。
OC代碼以下:
1
2
3
4
5
6
|
// Toggle between a vertical and horizontal stack
if (self.stackView.axis == UILayoutConstraintAxisHorizontal) {
self.stackView.axis = UILayoutConstraintAxisVertical;
}else {
self.stackView.axis = UILayoutConstraintAxisHorizontal;
}
|
Swift代碼以下:
1
2
3
4
5
6
|
// Toggle between a vertical and horizontal stack
if stackView.axis == .Horizontal {
stackView.axis = .Vertical
}else {
stackView.axis = .Horizontal
}
|
對於被管理的子視圖的 hidden 屬性的變化和 stack 視圖屬性的變化,你能夠經過將這些改變內置到一個動畫塊代碼的方式以動畫方式展示。
OC代碼以下:
1
2
3
4
5
|
// Animates removing the first item in the stack.
[UIView animateWithDuration:0.25 animations:^{
UIView * firstView = self.stackView.arrangedSubviews[0];
firstView.hidden = YES;
}];
|
Swift代碼以下:
1
2
3
4
|
// Animates removing the first item in the stack.
UIView.animateWithDuration(0.25) { () -> Void in
let firstView = stackView.arrangedSubviews[0]
firstView.hidden = true}
|
最後,你能夠直接在Interface Builder中給不少 stack 視圖屬性定義特定的 「尺寸類」 類型值。系統將在 stack 視圖的尺寸類改變時動畫展示這些改變。
8、經常使用的方法
建立 Stack 視圖
1
|
- initWithArrangedSubviews: (New in iOS 9.0)
|
管理安排的子視圖
1
2
3
4
|
- addArrangedSubview: (New in iOS 9.0)
arrangedSubviews Property (New in iOS 9.0)
- insertArrangedSubview:atIndex: (New in iOS 9.0)
- removeArrangedSubview: (New in iOS 9.0)
|
設置佈局
1
2
3
4
5
6
|
alignment Property (New in iOS 9.0)
axis Property (New in iOS 9.0)
baselineRelativeArrangement Property (New in iOS 9.0)
distribution Property (New in iOS 9.0)
layoutMarginsRelativeArrangement Property (New in iOS 9.0)
spacing Property (New in iOS 9.0)
|
常量
1
2
|
UIStackViewDistribution
UIStackViewAlignment
|
本文原文及圖片來源:UIStackView Class Reference