同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。