UIStackView
UIStackView介紹
隨著autolayout的推廣開來,更多的app開始使用自動布局的方式來構建自己的UI系統(tǒng),autolayout配合storyBoard和一些第三方的框架,對于創(chuàng)建約束來說,已經(jīng)十分方便,但是對于一些動態(tài)的線性布局的視圖,我們需要手動添加的約束不僅非常多,而且如果我們需要插入或者移除其中的一些UI元素的時候,我們又要做大量的修改約束的工作,UIStackView正好可以解決這樣的問題。
UIStackView 是 iOS 9 中新增的一個控件,它繼承于UIView,用來管理一行或一列視圖的布局(堆疊視圖的控制器類視圖,所謂堆疊視圖時一種平鋪式的線性布局方式,不可重疊,布局方向也不可交錯)
。UIStackView新增了幾個屬性,這些屬性就是子視圖布局規(guī)則。一旦UIStackView的這些屬性發(fā)生變化,它的arrangedSubviews就會按照規(guī)則重新排布。只要我們掌握這些規(guī)則,就可以管理視圖布局了。如果能再稍加靈活運用,有時候我們甚至能輕松實現(xiàn)一些精妙布局。 UIStackView可以幫助開發(fā)者更加簡單的使用layout而不必手動添加太多布局約束.
屬 性 | 作 用 |
---|---|
Axis | 屬性決定了 stack 的朝向,只有垂直或水平 |
distribution | 屬性決定了其管理的視圖在沿著其軸向上的布局 |
Alignment | 屬性決定了其管理的視圖在垂直于其軸向上的布局 |
Spacing | 屬性決定了其管理的視圖間的最小間隙 |
layoutMarginsRelativeArrangement | 屬性決定了 stack 視圖平鋪其管理的視圖時是否要參照它的布局邊距 |
baselineRelativeArrangement | 屬性決定了 stack 視圖平鋪其管理的視圖時是否要參照它的布局邊距 |
![Uploading 19_081418.png . . .]
](http://upload-images.jianshu.io/upload_images/1129706-a300c78a3ddc0cdb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
UIStackViewDistribution
axis
、spacing
、distribution
和alignment
是比較重要的4個屬性,他們都能給布局帶來明顯的變化。axis
和spacing
屬性作用單一,通過屬性解釋或者通過視圖簡單觀察我們就能理解他們的作用。distribution
和alignment
這兩個屬性相對而言更具靈活性,也更具有難度,尤其是二者的結合使用。
public enum UIStackViewDistribution : Int {
case fill
case fillEqually
case fillProportionally
case equalSpacing
case equalCentering
}
public enum UIStackViewAlignment : Int {
case fill
case leading
public static var top: UIStackViewAlignment { get }
case firstBaseline
case center
case trailing
public static var bottom: UIStackViewAlignment { get }
case lastBaseline
}
UIStackViewDistributionFill
將arrangedSubviews填充滿整個StackView,他們之間的間隙等于spacing大小
如果減去所有的spacing,所有arrangedSubview的固有尺寸(intrinsicContentSize)之和不能填滿StackView,那么就按照Hugging的優(yōu)先級將其拉伸。反之,如果超出StackView的尺寸則按CompressionResistance的優(yōu)先級壓縮。如果優(yōu)先級相同,就按排列順序來拉伸或壓縮。
UIStackViewDistributionFillEqually
每個arrangedSubview沿axis方向的長度相等,等于StackView沿axis長度減去spacing之和除以arrangedSubviews個數(shù)。
-
UIStackViewDistributionFillProportionally
根據(jù)arrangedSubview的intrinsicContentSize,將StackView沿axis方向的長度減去spacing之和按比例分配給arrangedSubviews。
-
UIStackViewDistributionEqualSpacing
先按arrangedSubviews的intrinsicContentSize布局,然后余下的空間均分為spacing
如果spacing小于StackView設置的spacing,則按照CompressionResistance的優(yōu)先級來壓縮arrangedSubviews。
-
UIStackViewDistributionEqualCentering
令arrangedSubviews的中心點之間的距離相等,且spacing大于等于StackView設置的spacing(每兩個arrangedSubview之間的spacing可能不相等)
如果spacing小于StackView設置的spacing,則按照CompressionResistance的優(yōu)先級來壓縮arrangedSubviews。
UIStackViewalignment
-
UIStackViewAlignmentFill
在StackView軸向的垂直方向上拉伸所有子view來填充StackView
-
UIStackViewAlignmentLeading
用于stackview是垂直軸向時,所有子view靠左對齊
-
UIStackViewAlignmentTop
用于stackview是水平軸向時,所有子view靠頂部對齊
-
UIStackViewAlignmentCenter
在StackView軸向的垂直方向上子視圖以中線為基準對齊
-
UIStackViewAlignmentTrailing
用于stackview是垂直軸向時,所有子view靠右對齊
-
UIStackViewAlignmentBottom
用于stackview是水平軸向時,所有子view靠底部對齊
-
UIStackViewAlignmentFirstBaseline
用于stackview是水平軸向時,按照第一個子視圖中文字的第一行對齊
-
UIStackViewAlignmentLastBaseline
用于stackview是水平軸向時,按照最后一個子視圖中文字的最后一行對齊
storyboard添加StackView
- IB
從對象庫中拖拽UIStackView到storyboard中,然后往內部扔控件(UIView或其子類)就可以了。
選擇storyboard中的控件,可以用“command鍵 + 單擊”進行多選,然后點擊下方的stack按鈕,這樣選中的控件就會被放入一個StackView中。
代碼添加StackView
- 創(chuàng)建
UIStackView
UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[forkingLabel, logoImageView, dogLabel]];
stackView.translatesAutoresizingMaskIntoConstraints = NO;
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.distribution = UIStackViewDistributionFill;
stackView.alignment = UIStackViewAlignmentCenter;
stackView.spacing = 0;
[self.view addSubview:stackView];
- 動態(tài)的改變其中view的個數(shù)
UIView * newView = [[UIView alloc]init];
[stackView addArrangedSubview:newView];
特別注意:addArrangedSubview
和addSubview
有很大的區(qū)別,使用前者是將視圖添加進StackView
的布局管理,后者只是簡單的加在視圖的層級上,并不接受StackView
的布局管理。
- 與之相對,我們可以使用下面的方法移除一個view
UIView * view = [stackView arrangedSubviews].lastObject;
[stackView removeArrangedSubview:view];
StackView使用技巧
- 嵌套 只要嵌套好UIStackView,就可以用很少的約束達到自動布局界面的目的
使用StackView 嵌套 模仿同程首頁布局
- 結合sizeClass 多屏幕適配
查看SatckView的Attributes Inspector,我們會發(fā)現(xiàn)StackView的幾個主要屬性都是可以設置sizeclass模式的,
這對我們的屏幕適配將會大有助益。再加上約束的sizeClass,靈活性可以想象。
- 因為
StackView
繼承于UIView
,因此在布局改變的時候,我們可以使用UIView
層的動畫 添加view的時候會有動畫效果,移除的時候沒有
[stackView addArrangedSubview:newView];
[UIView animateWithDuration:1 animations:^{
[stackView layoutIfNeeded];
}];
FDStackView
UIStackView
是在iOS9
才推出的,最低支持的系統(tǒng)也是iOS9
, FDStackView
出現(xiàn)了,它就是為了解決UIStackView
在低于iOS9
的系統(tǒng)下無法使用的問題
在FDStackView
之前也已經(jīng)有了一些類似的開源項目,比如OAStackView
和TZStackView
,然而他們都不能滿足我們的需求,局限性還是比較大的,比如不支持IB
,某些功能還沒有實現(xiàn),類名需要使用非UIStackView
,在我們看來這些對開發(fā)者來說都是不友好的,開發(fā)者需要的是一款功能完善,支持IB
,使用時完全無感,在Xcode7
上直接使用UIStackView
即可,接下來的事情交給FDStackView
就好,它負責將UIStackView
在低于iOS9的系統(tǒng)上運行。
需要注意如果使用IB的話,那么IB
的Builds for
屬性需要設置為iOS 9.0 and later
-
forkingdog
開源小組的成員實現(xiàn)原理介紹
- FDStackView —— Downward Compatible UIStackView (Part 1)
- FDStackView —— Downward Compatible UIStackView (Part 2)
- FDStackView —— Downward Compatible UIStackView (Part 3)