最近从同事那里了解到UIStackView这个API,以前使用到的自动布局有代码自动布局(Masonary)和拖 constraint 这两种。UIStackView和这两种相比能够减小重复繁琐的工做,使自动布局变得方便快捷。github
UIStackView是苹果推出的一套能够自动布局的API,适配iOS9.0以后,iOS8.0以前的不支持,UIStackView是一个容器,UIStackView继承自UIView,可是它自己不能自我渲染,好比为他设置 backgroundColor 是无效的,因此它要和 UIView 相辅相成的进行工做。它可以帮助 UIView 来处理 子视图 的位置和大小等布局问题。他的定位是介于 手写约束 和 UITableView/UICollectionView 之间的工具。数组
UIStackView通常用于实现水平平铺一行或者垂直平铺一行的视图组合。bash
用一个简图表示一下UIStackView和父视图以及子视图之间的继承关系工具
代码初始化一个stackView并添加到父视图上布局
- (void)initStackView{
self.stackView = [[UIStackView alloc] init];
self.stackView.axis = UILayoutConstraintAxisHorizontal;
self.stackView.distribution = UIStackViewDistributionFill;
self.stackView.spacing = 10;
self.stackView.alignment = UIStackViewAlignmentFill;
self.stackView.frame = CGRectMake(0, 100, ScreenWidth, 200);
[self.view addSubview:self.stackView];
}
复制代码
决定了 stack 的朝向,只有垂直或水平;ui
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
UILayoutConstraintAxisHorizontal = 0,//水平布局方向
UILayoutConstraintAxisVertical = 1//垂直布局方向
};
复制代码
描述了其管理的子视图在沿着其轴向(axis)上的布局关系;spa
typedef NS_ENUM(NSInteger, UIStackViewDistribution) {
UIStackViewDistributionFill = 0,
UIStackViewDistributionFillEqually,
UIStackViewDistributionFillProportionally,
UIStackViewDistributionEqualSpacing,
UIStackViewDistributionEqualCentering,
} NS_ENUM_AVAILABLE_IOS(9_0);
复制代码
它就是将 arrangedSubviews 填充满整个 StackView ,若是设置了spacing,那么这些 arrangedSubviews 之间的间距就是spacing。若是减去全部的spacing,全部的 arrangedSubview 的固有尺寸( intrinsicContentSize )不能填满或者超出 StackView 的尺寸,那就会按照 Hugging 或者 CompressionResistance 的优先级来拉伸或压缩一些 arrangedSubview 。若是出现优先级相同的状况,就按排列顺序来拉伸或压缩。3d
这种就是 StackView 的尺寸减去全部的spacing以后均分给 arrangedSubviews ,每一个 arrangedSubview 的尺寸是相同的。code
这个和FillEqually差很少,只是这个不是将尺寸均分给 arrangedSubviews ,而是根据 arrangedSubviews 的 intrinsicContentSize 按比例分配。
这种是使 arrangedSubview 之间的spacing相等,可是这个spacing是有可能大于 StackView 所设置的spacing,可是绝对不会小于。这个类型的布局能够这样理解,先按全部的 arrangedSubview 的 intrinsicContentSize 布局,而后余下的空间均分为spacing,若是大约 StackView 设置的spacing那这样就OK了,若是小于就按照 StackView 设置的spacing,而后按照 CompressionResistance 的优先级来压缩一个 arrangedSubview 。
这种是使 arrangedSubview 的中心点之间的距离相等,这样没两个 arrangedSubview 之间的spacing就有可能不是相等的,可是这个spacing仍然是大于等于 StackView 设置的spacing的,不会是小于。这个类型布局仍然是若是 StackView 有多余的空间会均分给 arrangedSubviews 之间的spacing,若是空间不够那就按照 CompressionResistance 的优先级压缩 arrangedSubview 。
决定了其管理的视图在垂直于其轴向上的布局;
typedef NS_ENUM(NSInteger, UIStackViewAlignment) {
UIStackViewAlignmentFill,//子视图填充StackView
UIStackViewAlignmentLeading,//子视图左对齐(axis为垂直方向而言)
UIStackViewAlignmentTop = UIStackViewAlignmentLeading,//子视图顶部对齐(axis为水平方向而言)
UIStackViewAlignmentFirstBaseline, // 按照第一个子视图的文字的第一行对齐,同时保证高度最大的子视图底部对齐(只在axis为水平方向有效)
UIStackViewAlignmentCenter,//子视图居中对齐
UIStackViewAlignmentTrailing,//子视图右对齐(axis为垂直方向而言)
UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,//子视图底部对齐(axis为水平方向而言)
UIStackViewAlignmentLastBaseline, // 按照最后一个子视图的文字的最后一行对齐,同时保证高度最大的子视图顶部对齐(只在axis为水平方向有效)
} NS_ENUM_AVAILABLE_IOS(9_0);
复制代码
默认方式, 若是子控件水平布局, 则指子控件的垂直方向填充满stackView. 反之亦然。
若是子控件竖直布局, 则指子控件左边对齐stackView左边. 反之亦然。
按照第一个子视图的文字的第一行对齐,同时保证高度最大的子视图底部对齐(只在axis为水平方向有效)
子视图居中对齐。
子视图右对齐(axis为垂直方向而言)。
axis为水平时UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing。
按照最后一个子视图的文字的最后一行对齐,同时保证高度最大的子视图顶部对齐(只在axis为水平方向有效)
设置子视图之间的间距,是子视图之间的最小间距,之因此说是最小间距,由于stackView会根据必定的规则对内部空间布局,有的时候不能知足全部要求,好比stackView 自己宽度100,内部两个控件,宽度都为100,100+100+10就超过了自己宽度, 这时会压缩其中一个子控件的宽度来知足最小间距。
决定了其视图间的垂直间隙是否根据基线测量获得。
决定了 stackView 平铺其管理的子视图时是否要参照它的布局边距,若是是YES则经过 layout margins 布局,为NO则经过 bounds布局。
-initWithArrangedSubviews: (New in iOS 9.0):初始化子视图数组
-addArrangedSubview: (New in iOS 9.0): 添加子视图
3.2.2 -arrangedSubviews Property (New in iOS 9.0): UIStackView使用arrangedSubviews数组来管理子视图。
3.2.3 -insertArrangedSubview:atIndex: (New in iOS 9.0):根据下标插入视图
-removeArrangedSubview: (New in iOS 9.0):移除子视图
注意:addArrangedSubview和insertArrangedSubview,会把子视图添加到arrangedSubviews数组的同时也添加到StackView上,可是removeArrangedSubview,只会把子视图从arrangedSubviews数组中移除,不会从subviews中移除,若是须要可调用removeFromSuperview。
附上gitHub demo
UIStackView能够经过代码或者xib实现,平时工做中一边使用代码实现,代码更方便后期项目的功能修改,更便于维护。学会它的使用能方便咱们快速开发新功能。但愿能和你们探讨更多关于UIStackView的知识。