iOS9 UIStackView 簡介

做者:Umberto Raimondi,原文連接,原文日期:2015-12-08
譯者:CoderAFI;校對:Channe;定稿:shanksios

示例程序採用 Swift2.0 編寫,須要用 Xcode7 進行編譯,能夠訪問 Github 或者 zipped 下載本文源代碼git

iOS9 新加入了一個很是易用的佈局控件 UIStackView,它能夠將一組 UIView 視圖進行垂直或水平方向的排列,用來替換手工使用 Auto Layout 對視圖進行佈局。github

每一個 UIStackView 控件均可以在垂直和水平方向上排列展現一組 subviews,並能夠根據當前屏幕大小和方向的變化動態調整它的內容,感受起來就像是一個隱形的容器。實際上 subviews 的位置是根據設置的對齊、間距和大小屬性來決定的。swift

內部的原理是 UIStackView 類幫你管理了 Auto Layout 約束。想象一下 UIStackView 其實就是一個基於 Auto Layout 的抽象層從而使佈局屬性的建立簡單化。你能夠在一個主 UIStackView 中嵌套 UIStackView 從而讓視圖精確放置到相應的位置。ide

若是你作過 Android 開發,你會發現 UIStackView 概念跟 Android 中最經常使用的佈局控件 LinearLayout 很是類似,這些佈局的想法其實都是從早期的 Java Swing 開發中借鑑過來並加以完善的。工具

基礎

UIStackView 既能夠用代碼編寫也能夠在 Interface Builder 中設計。佈局

在 Interface Builder 中你能夠從 Object Library 控件選擇工具集裏找到垂直或者水平對齊的 UIStackView 並添加到相應位置,而後就能夠在 UIStackView 上添加新的視圖了。測試

UIStackView 一樣也能夠對現有的一些視圖進行包裝,只須要選擇他們並點擊 Interface Builder 底部工具欄新加的Stack icon圖標便可。動畫

很是簡單,可是咱們的教程將用代碼的方式實現一個簡單的嵌套佈局。ui

在這個簡單的示例程序中,咱們將會在狀態欄下放置一個 UIStackView,裏面包含四個控件:兩個 UILabel,一個水平方向的 UIStackView 和 一個 UIButton。水平方向的 UIStackView 中包含了三個帶有默認圖標的按鈕。

下面讓咱們建立一個 Single View Application,記住要將 Deployment Target 設置成 9.0+。

打開 ViewController 類並用下面的代碼替換 viewDidLoad 方法:

var stackView:UIStackView!
var nestedStackView = UIStackView()

override func viewDidLoad() {
    super.viewDidLoad()

    stackView.translatesAutoresizingMaskIntoConstraints=false
    self.view.addSubview(stackView)
    // Main UIStackView contraints, nearly fills its parent view
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-30-[stackView]-30-|",options: NSLayoutFormatOptions.AlignAllLeading,metrics: nil, views: ["stackView":stackView]))
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[stackView]-10-|",options: NSLayoutFormatOptions.AlignAllLeading,metrics: nil, views: ["stackView":stackView]))

    stackView.axis = .Vertical
    stackView.alignment = .Fill
    stackView.spacing = 25
    stackView.distribution = .FillEqually

    var lbl = UILabel()
    lbl.text ="Label 1"
    lbl.backgroundColor = UIColor.redColor()
    stackView.addArrangedSubview(lbl)

    lbl = UILabel()
    lbl.text = "Label 2"
    lbl.backgroundColor = UIColor.greenColor()
    stackView.addArrangedSubview(lbl)

    nestedStackView.axis = .Horizontal
    nestedStackView.alignment = .Fill
    nestedStackView.spacing = 25
    nestedStackView.distribution = .FillEqually
    nestedStackView.addArrangedSubview(UIButton(type: .InfoDark))
    nestedStackView.addArrangedSubview(UIButton(type: .InfoLight))
    nestedStackView.addArrangedSubview(UIButton(type: .ContactAdd))
    stackView.addArrangedSubview(nestedStackView)

    let btn = UIButton(type: .System)
    btn.setTitle("Press Me", forState: .Normal)
    stackView.addArrangedSubview(btn)
}

爲了指定主 UIStackView 是垂直方向佈局的咱們把 axis 屬性設置成 .Vertical,前三個控件將會等間距排列,剩下的UIButton會填充剩餘的可用空間。在嵌套 UIStackView 中的三個默認按鈕也是用一樣的方式來排列。alignmentdistributionspacing 三個屬性會在下面單獨講解,這裏咱們先忽略它們。

有時候你可能須要將部分視圖隱藏起來或者顯示出來,這對於 UIStackView 來講實現起來是很是容易的,你只須要設置相應視圖的 hidden 屬性就能夠。

爲了方便測試,咱們給 UIButton 添加一個 pressedMe 的點擊事件響應方法:

...
    btn.setTitle("Press Me", forState: .Normal)
    btn.addTarget(self, action: "pressedMe:", forControlEvents: UIControlEvents.TouchUpInside)
    stackView.addArrangedSubview(btn)

}

func pressedMe(sender: UIButton!){
    UIView.animateWithDuration(0.5) {
        self.nestedStackView.hidden = !self.nestedStackView.hidden
    }
}

當點擊這個按鈕時,主 UISTackView 和 內部的 UISTackView 將會根據在 viewDidLoad 中設置的屬性從新佈局內部的子視圖並帶有短暫的顯示或者隱藏動畫效果。

若是須要,subviews 也能夠徹底從 UIStackView 中移除而後剩下的子視圖也會根據各自的屬性從新佈局。

func pressedMe(sender: UIButton!){
   stackView.removeArrangedSubview(nestedStackView)
   nestedStackView.removeFromSuperview()
}

這個移除的操做須要兩步,第一步是調用 removeArrangedSubview 方法用來從 UIStackView 刪除視圖而且從新佈局剩餘的 subviews 可是實際上並無從父視圖上刪除。第二部就是調用 removeFromSuperview 方法以保證該視圖從父視圖中徹底的被刪除。

UIStackView: Alignment, Distribution And Spacing 屬性

下面讓咱們詳細瞭解下 UIStackView 的佈局屬性:

StackProperty

Axis 軸

定義子視圖的佈局方向,包含 Vertical(垂直) 和 Horizontal(水平)兩個枚舉值。

Alignment 對齊

alignment 屬性指定了子視圖在佈局方向上的對齊方式,若是值是 Fill 則會調整子視圖以適應空間變化,其餘的值不會改變視圖的大小。有效的值包含:Fill、 Leading、 Top、 FirstBaseline、 Center、 Trailing、 Bottom、 LastBaseline。

Distribution 分佈

Distribution 屬性定義了 subviews 的分佈方式,能夠賦值的5個枚舉值能夠分爲兩組: Fill 組 和 Spacing 組。

Fill 組用來調整 subviews 的大小,同時結合 spacing 屬性來肯定 subviews 之間的間距。

  • Fill: subviews 將會根據本身內容的內容阻力(content resistance)或者內容吸附優先級(hugging priority)進行動態拉伸,若是沒有設置該值,subviews 中的一個子視圖將會用來填充剩餘可用空間。

  • FillEqually: 忽略其餘的約束,subviews 將會在設置的佈局方向上等寬或等高排列。

  • FillProportionally: subviews 將會根據本身的原始大小作適當的佈局調整。

Spacing 組指定了 subviews 在佈局方向上的間距填充方式,當 subviews 不知足佈局條件或有不明確的的 Auto Layout 設置時,該類型的值就會結合相應的壓縮阻力(compression resistance) 來改變 subviews 的大小。

  • EqualSpacing: subviews 等間距排列

  • EqualCentering: 在佈局方向上居中的 subviews 等間距排列

Spacing 間距

spacing 屬性根據當前 distribution 屬性的值有不一樣方向的解釋。

若是 UIStackView 的 distribution 屬性設置的是 EqualSpacing、 EqualCentering,spacing 屬性指的就是 subviews 之間的最小間距。相反若是設置的是 FillProportionally 屬性,那麼 spacing 的值就是嚴格的間距值。

iOS7+ 兼容

官方的 UIStackView 只在 iOS9 以上系統可使用,可是其餘的開源組織在低版本的系統上也實現了相應的功能:

本文由 SwiftGG 翻譯組翻譯,已經得到做者翻譯受權,最新文章請訪問 http://swift.gg

相關文章
相關標籤/搜索