同iOS以往每一個迭代同樣,iOS 9帶來了不少新特性。UIKit框架每一個版本都在改變,而在iOS 9比較特別的是UIStackView,它將從根本上改變開發者在iOS上建立用戶界面的方式。本文將帶你學習怎樣使用UIStackView建立用戶界面。html
本文假定你已經熟悉Auto Layout基礎。不熟悉的能夠先看看Auto Layout教程。要理解Stack View爲什麼如此有用及它是如何起做用的,須要首先對Auto Layout有深刻了解。android
1. 實例預覽git
咱們將使用UIStackView模擬一個app評分提示。用戶能夠增長星星或者移除星星來打分。完成後看起來是這樣。github
先從GitHub下載樣例工程並打開。在Main.Storyboard裏有兩個Stack View數組
咱們將使用這兩個Stack View來佈局界面。開始編碼前,讓咱們先看一下Stack View是如何工做的。xcode
2. UIStackView 概述app
Stack View的核心即是方便垂直或水平排布多個subview,若是你作過Android開發,那它和LinearLayout 控件很是類似。框架
Stack View最有用的就是它會自動爲每一個subview建立和添加Auto Layout constraints。固然你能夠控制subview的大小和位置。能夠經過選項配置subview的大小、排布以及彼此間的間距。ide
佈局內容佈局
打開Main.Storyboard,選擇其中一個Stack View能夠查看其選項,並選中一個Stack View。在 Attributes Inspector中,注意Stack View下面列出的選擇。
Axis表示Stack View的subview是水平排布仍是垂直排布。Alignment控制subview對齊方式。Distribution定義subview的分佈方式。Spacing 爲subview間的最小間距。
把術語簡化一下,你可這樣理解:Alignment 用於控制X 和 Y值,而Distribution 用於控制高度和寬度。另兩個值都會影響對齊。若是選中Baseline Relative將根據subview的基線調整垂直間距。若是選中Layout Margins Relative 將相對於標準邊界空白來調整subview位置。
另外一個須要記住的是,Stack View會被當成Container View。因此它是一個不會被渲染的UIView子類。它不像其餘UIView子類同樣,會被渲染到屏幕上。這也意味着設置其backgroundColor屬性或重載drawRect:方法都不會產生任何效果。
subView和arrangedSubView
開始使用Stack View前,咱們先看一下它的屬性subViews和arrangedSubvies屬性的不一樣。若是你想添加一個subview給Stack View管理,你應該調用addArrangedSubview:或insertArrangedSubview:atIndex: arrangedSubviews數組是subviews屬性的子集。
要移除Stack View管理的subview,須要調用removeArrangedSubview:和removeFromSuperview。移除arrangedSubview只是確保Stack View再也不管理其約束,而非從視圖層次結構中刪除,理解這一點很是重要。
如今咱們對Stack View有必定了解,開始使用它。
3. 配置垂直佈局的Stack View
打開Main.Storyboard選擇上面的Stack View。對Attributes Inspector做以下改變:
Alignment 設爲 Center
Distribution 設爲 Equal Spacing
Spacing 設爲 30
這告訴Stack View爲subview添加約束,使其垂直居中並沿Stack View的軸線對稱,而後爲subview設置邊距30。
若是subview大小和Stack View內容區不相符,將根據compression resistance priorities對subview進行拉伸或壓縮。在運行時給Stack View添加subview也一樣會如此。
佈局有任何歧義Stack View都會根據subview在arrangedSubviews中index一步步回退去調整subview的大小,直至其恰好適應Stack View的大小。
4. 給Stack View添加垂直佈局的Subview
添加一個label,一個image view和一個button到上面的Stack View裏。label在最上面,image view在中間,button在下面。添加完成後看起來是這樣:
接下來,咱們要在Attributes Inspector裏修改一下剛纔添加的subview的屬性。把label的文本祕訣成「How do you likeour app?」, Text Alignment選擇Center 。image view的Image 輸入「logo」, Content Mode選Aspect Fit。最後把button的Text 設置成「Add Star!」。
運行app。能看到咱們只作了不多工做,但已經添加了三個能響應方向、size class等改變的subview。事實上你並不需手動添加任何約束。
當app運行時,點擊Xcode窗口底部Debug View Hierarchy按鈕能夠進行實時視圖調試
選擇先前添加的任意一個subview。查看size inspector,咱們注意到Stack View已經自動爲其添加了約束。下圖顯示的是爲button添加的約束
5. 添加五角星
按鈕事件還沒和app界面關聯,咱們先關聯起來。中止運行app,打開storyboard。建立一個名爲addStar的IBAction 關聯到按鈕的Touch Up Inside事件。
addStar(_:)方法實現:
1
2
3
4
5
6
7
|
@IBAction func addStar(sender: AnyObject) {
let starImgVw:UIImageView = UIImageView(image: UIImage(named:
"star"
))
self.horizontalStackView.addArrangedSubview(starImgVw)
UIView.animateWithDuration(0.25, animations: {
self.horizontalStackView.layoutIfNeeded()
})
}
|
給水平佈局的Stack View裏的星星image添加動畫。記住,因爲Stack View自動爲咱們管理Auto Layout constraints,咱們只能調用layoutIfNeeded來實現動畫。
編譯運行app,點擊add star按鈕。能看到最後結果卻不盡人意。
選擇下面的Stack View,查看Attributes Inspector會看到問題所在。因爲Alignment 和Distribution 都設置成了Fill,Stack View 拉伸了星星以適應其大小。
這在添加更多的星星的時候會引發更多問題。咱們但願星星居中顯示,而不是被拉伸來適應Stack View的寬度。
修改Alignment 的值爲Center ,修改Distribution 的值爲Fill Equally。最後在addStar(_:)方法中設置image view的內容。
1
2
3
4
5
6
7
8
|
@IBAction func addStar(sender: AnyObject) {
let starImgVw:UIImageView = UIImageView(image: UIImage(named:
"star"
))
starImgVw.contentMode = .ScaleAspectFit
self.horizontalStackView.addArrangedSubview(starImgVw)
UIView.animateWithDuration(0.25, animations: {
self.horizontalStackView.layoutIfNeeded()
})
}
|
運行app,點幾回添加按鈕,咱們發現全部星星居中了。
6. Stack View嵌套
不能刪除星星,咱們的app評分什麼用處不大。打開storyboard,添加一個水平佈局的Stack View到上面的Stack View裏。把它放置在logo之下,按鈕之上。
把「Add Star!」按鈕拖到新添加的Stack View裏,再添加一個按鈕到新的Stack View裏。改變按鈕的title爲「Remove Star」,文本顏色設爲red。預覽以下:
在Attributes Inspector中編輯新Stack View的屬性,改變以下:
Alignment 設爲 Center
Distribution 設爲 Equal Spacing
Spacing 設爲 10
7. 刪除五角星
爲「Remove Star」按鈕建立名爲removeStar,事件類型爲Touch Up Inside的IBAction響應方法。
removeAction(_:)實現:
1
2
3
4
5
6
7
8
9
10
11
|
@IBAction func removeStar(sender: AnyObject) {
let star:UIView? = self.horizontalStackView.arrangedSubviews.last
if
let aStar = star
{
self.horizontalStackView.removeArrangedSubview(aStar)
aStar.removeFromSuperview()
UIView.animateWithDuration(0.25, animations: {
self.horizontalStackView.layoutIfNeeded()
})
}
}
|
運行app,如今既可增長,也可刪除了。改變模擬器方向或者旋轉設備看看app會怎樣調整其界面。咱們並未添加一行約束就構建好了app的用戶界面。
須要注意的是:removeStar(_:)裏調用removeFromSuperview是把subview從視圖層級中移除。再次調用removeArrangedSubview(_:)只是告訴Stack View再也不須要管理subview的約束。而subview會一直保持在視圖層級結構中直到調用removeFromSuperview把它移除。
結論
UIStackView類大大簡化了用戶界面開發。這是好事,特別是隨着硬件的改變。使用UIStackView,減小了開發者爲簡單場景設置枯燥的約束,把繁雜的工做交給了UIKit。