UIStackView
UIStackView介绍
随着autolayout的推广开来,更多的app开始使用自动布局的方式来构建自己的UI系统,autolayout配合storyBoard和一些第三方的框架,对于创建约束来说,已经十分方便,但是对于一些动态的线性布局的视图,我们需要手动添加的约束不仅非常多,而且如果我们需要插入或者移除其中的一些UI元素的时候,我们又要做大量的修改约束的工作,UIStackView正好可以解决这样的问题。
UIStackView 是 iOS 9 中新增的一个控件,它继承于UIView,用来管理一行或一列视图的布局(堆叠视图的控制器类视图,所谓堆叠视图时一种平铺式的线性布局方式,不可重叠,布局方向也不可交错)
。UIStackView新增了几个属性,这些属性就是子视图布局规则。一旦UIStackView的这些属性发生变化,它的arrangedSubviews就会按照规则重新排布。只要我们掌握这些规则,就可以管理视图布局了。如果能再稍加灵活运用,有时候我们甚至能轻松实现一些精妙布局。 UIStackView可以帮助开发者更加简单的使用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的优先级将其拉伸。反之,如果超出StackView的尺寸则按CompressionResistance的优先级压缩。如果优先级相同,就按排列顺序来拉伸或压缩。
UIStackViewDistributionFillEqually
每个arrangedSubview沿axis方向的长度相等,等于StackView沿axis长度减去spacing之和除以arrangedSubviews个数。
-
UIStackViewDistributionFillProportionally
根据arrangedSubview的intrinsicContentSize,将StackView沿axis方向的长度减去spacing之和按比例分配给arrangedSubviews。
-
UIStackViewDistributionEqualSpacing
先按arrangedSubviews的intrinsicContentSize布局,然后余下的空间均分为spacing
如果spacing小于StackView设置的spacing,则按照CompressionResistance的优先级来压缩arrangedSubviews。
-
UIStackViewDistributionEqualCentering
令arrangedSubviews的中心点之间的距离相等,且spacing大于等于StackView设置的spacing(每两个arrangedSubview之间的spacing可能不相等)
如果spacing小于StackView设置的spacing,则按照CompressionResistance的优先级来压缩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
- 创建
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];
- 动态的改变其中view的个数
UIView * newView = [[UIView alloc]init];
[stackView addArrangedSubview:newView];
特别注意:addArrangedSubview
和addSubview
有很大的区别,使用前者是将视图添加进StackView
的布局管理,后者只是简单的加在视图的层级上,并不接受StackView
的布局管理。
- 与之相对,我们可以使用下面的方法移除一个view
UIView * view = [stackView arrangedSubviews].lastObject;
[stackView removeArrangedSubview:view];
StackView使用技巧
- 嵌套 只要嵌套好UIStackView,就可以用很少的约束达到自动布局界面的目的
使用StackView 嵌套 模仿同程首页布局
- 结合sizeClass 多屏幕适配
查看SatckView的Attributes Inspector,我们会发现StackView的几个主要属性都是可以设置sizeclass模式的,
这对我们的屏幕适配将会大有助益。再加上约束的sizeClass,灵活性可以想象。
- 因为
StackView
继承于UIView
,因此在布局改变的时候,我们可以使用UIView
层的动画 添加view的时候会有动画效果,移除的时候没有
[stackView addArrangedSubview:newView];
[UIView animateWithDuration:1 animations:^{
[stackView layoutIfNeeded];
}];
FDStackView
UIStackView
是在iOS9
才推出的,最低支持的系统也是iOS9
, FDStackView
出现了,它就是为了解决UIStackView
在低于iOS9
的系统下无法使用的问题
在FDStackView
之前也已经有了一些类似的开源项目,比如OAStackView
和TZStackView
,然而他们都不能满足我们的需求,局限性还是比较大的,比如不支持IB
,某些功能还没有实现,类名需要使用非UIStackView
,在我们看来这些对开发者来说都是不友好的,开发者需要的是一款功能完善,支持IB
,使用时完全无感,在Xcode7
上直接使用UIStackView
即可,接下来的事情交给FDStackView
就好,它负责将UIStackView
在低于iOS9的系统上运行。
需要注意如果使用IB的话,那么IB
的Builds for
属性需要设置为iOS 9.0 and later
-
forkingdog
开源小组的成员实现原理介绍
- FDStackView —— Downward Compatible UIStackView (Part 1)
- FDStackView —— Downward Compatible UIStackView (Part 2)
- FDStackView —— Downward Compatible UIStackView (Part 3)