iOS9新特性——堆叠视图UIStackView
iOS9中,Apple又为开发者提供了一个新的布局视图,UIStackView可以帮助开发者更加简单的使用layout而不必手动添加太多布局约束。
一、引言
随着autolayout的推广开来,更多的app开始使用自动布局的方式来构建自己的UI系统,autolayout配合storyBoard和一些第三方的框架,对于创建约束来说,已经十分方便,但是对于一些动态的线性布局的视图,我们需要手动添加的约束不仅非常多,而且如果我们需要插入或者移除其中的一些UI元素的时候,我们又要做大量的修改约束的工作,UIStackView正好可以解决这样的问题。
二、在storyBoard上初识StackView
UIStackView是一个管理一组堆叠视图的控制器类视图,所谓堆叠视图时一种平铺式的线性布局方式,不可重叠,布局方向也不可交错,如果你做过watchOS的开发,你会发现,其实StackView与watchOS中的group十分能相似。
例如,我们如果需要一个如下效果的布局,在屏幕的中间摆放几个大小一致的色块,无论屏幕朝向如何,其位置都不会变化,并且可以向其中添加和移除色块的数量:
首先,我们在ViewController中拉入一个stackView:
将一些属性设置如下:
Axis是设置布局的方向,有水平和垂直两种方式,一个StackView只能选择一种布局模式。
Alignment是选择其管理视图的对齐模式,我们这里选择充满。
Distribution是设置其管理视图的排列方式,我们选择等宽充满。
Spacing是设置视图之间的间距,设置为10.
之后有一点需要注意,stackView用于布局其内部管理的视图,对于它本身,我们还需要添加一些约束,将它约束在屏幕的中间。
我们向其中拖入任意数量的view,设置不同的颜色,就实现了我们想要的效果,并且可以随意动态删除和添加其中的view数量,不需要改变约束。
三、从代码学习UIStackView
通过代码创建一个UIStackView也非常简单,首先,我们先通过代码实现上面的效果:
NSMutableArray * array = [[NSMutableArray alloc]init];
for (int i =0 ; i<5; i++) {
UIView * view = [[UIView alloc]init];
view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
[array addObject:view];
}
UIStackView * stackView = [[UIStackView alloc]initWithArrangedSubviews:array];
[self.view addSubview:stackView];
[stackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view.mas_centerX);
make.centerY.equalTo(self.view.mas_centerY);
make.leading.equalTo(self.view.mas_leading).offset(20);
make.trailing.equalTo(self.view.mas_trailing).offset(-20);
make.size.height.equalTo(@100);
}];
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.distribution = UIStackViewDistributionFillEqually;
stackView.alignment = UIStackViewAlignmentFill;
效果图如下:
我们的布局没有问题,并且可以动态的改变其中view的个数,使用如下方法添加一个view:
UIView * newView = [[UIView alloc]init];
newView.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
[stackView addArrangedSubview:newView];
与之相对,我们可以使用下面的方法移除一个view:
UIView * view = [stackView arrangedSubviews].lastObject;
[stackView removeArrangedSubview:view];
特别注意:addArrangedSubview和addSubview有很大的区别,使用前者是将试图添加进StackView的布局管理,后者只是简单的加在试图的层级上,并不接受StackView的布局管理。
技巧:因为StackView继承于UIView,因此在布局改变的时候,我们可以使用UIView层的动画,如下:
//在添加view的时候会有动画效果,移除的时候没有
[stackView addArrangedSubview:newView];
[UIView animateWithDuration:1 animations:^{
[stackView layoutIfNeeded];
}];