最初教程由Jawwad Ahmad原创。Kevin Colligan更新支持iOS 十一、Xcode 9和Swift 4。bash
转载注明:www.rockerhx.com/2018/08/21/…app
iOS开发当中是否是遇到须要动态添加或者删除视图元素的需求。你是上基hub去嗨一遍第三方库仍是自行撸frame,或者用Auto Layout的约束更新。就这点破需求,反正我是坚定不选前二者,即使是万不得已,最多也是更新约束(虽然Auto Layout的所见即所得极大缩短了开发耗时,增长我撸猫的快乐时光,但不得不认可我是很反感用代码去改约束,可视化编码还要去code约束,脑子有病!!!)。 处理这类需求,总之一句话。 less
好在,如今你们伙应该都只支持到iOS9了,用上UIStackView
来处理这类需求简直是美滋滋,艾玛真香~~~ 在本教程中,阔以了解UIStackView
如何提供一种简单的方式来处理水平或垂直布局。还阔以了解如何经过使用对齐、分布和间距等属性来获取视图,以便自我调整方便自适应。编辑器
本教程假定观者基本熟悉Auto Layout。若是不熟悉,请移步传送门Beginning Auto Layout。ide
在这份UIStackView
教程中,咱们将使用一个名为“Vacation Spots”的应用程序。这个简单的应用阔以展现度假地点的一些基础信息。 不要方方脏脏的就开始动手,由于有几个问题须要咱们先用UIStackView
来处理下,并且比单独使用自动布局要简单得多。首先下载这个UIStackView教程的入门项目。打开项目并在iPhone模拟器上运行。你会看到一份度假地点清单。 工具
点击London那一栏,进入伦敦的信息视图。乍一看,好像还不错,但有几个问题。布局
既然咱们已经罗列好了改进工做,那就动手开始吧!!!动画
打开Main.storyboard。第一次这样作时,会要求您选择初始设备视图。这个视图在运行时没有效果,它针对不一样的设备调整大小,也只是让故事板的使用变得更加容易。iPhone 7或者8就好了。 ui
这些标签和按钮的各类背景色,运行时会被清除。在Storyboard中,它们只是视觉上的辅助,帮助显示改变StackView的各类属性将如何影响其嵌入视图的布局。
你如今不用管这些,若是在运行应用程序的时候你真的想看到背景色,你能够在SpotInfoViewController内部的**viewDidLoad()**中临时注释出如下几行。
// Clear background colors from labels and buttons
for view in backgroundColoredViews {
view.backgroundColor = UIColor.clear
}
复制代码
此外,全部的UI元素都使用了明确的占位内容,以便连接属性的时候更加明确方便,减少连错的可能性。
@IBOutlet weak var whyVisitLabel: UILabel!
复制代码
叨逼叨完了,let’s get started!
使用stack view
第一件事是修复按钮底部行之间的间距。stack view
能够以各类方式沿其轴分布其视图,其中一种方式是每一个视图之间的间距相等。 苹果为了推广新控件,咱们能够直接把想要的处理的控件元素直接一键压入stack view
。打开Spot Info View Controller故事版场景,按住Command
选中底部三个按钮。
点击右下角Show Document Outlin:
在左侧控件集列表内确认下是否是选对了按钮:
选中后,单击故事板画布右下角自动布局工具栏中的“新建堆栈”按钮:
按钮将嵌入到新的堆栈视图中:
如今出现了约束警告,
stack view
只是一种排版形式,是继承自UIView,它也是须要约束来肯定frame,只有肯定好自身的frame之后才能处理内部控件布局。
在stack view
中嵌入控件时,将删除对其的任何约束。例如,在将按钮嵌入stack view
以前,Submit Rating按钮的顶部有一个链接到Ratinglabel的垂直间距约束:
点击选中Submit Rating按钮能够看到它不在包含任何约束。
也阔以经过**Size inspector (⌥⌘5)**来查看控件约束状况:
接下来咱们须要为stack view
添加约束控制,若是整个页面的控件太多致使很差选中某个控件,直接从左侧的控件列表就好。
另外有个小技巧,按住Shift
再单击右键,Xcode会帮大忙。
最后经过右下角的Auto Layout toolbar添加约束便可。
保持Constrain to margins选中,而后添加以下约束。
Top: 20, Leading: 0, Trailing: 0, Bottom: 0
复制代码
按照如图所示输入数字直接tab就好,简单而快速的添加约束才是敏捷开发的首选。
控件之间如今看起来像是这样,stack view
会拉伸第一个控件来填充空间。
决定stack view
内部控件的分布属性为distribution
。目前,它被设置为Fill
,这意味着被包含的控件将沿着其轴彻底填充。为了实现这一点,stack view
将只拉伸其中一个视图来填充额外的空间;具体来讲,它会拉伸content hugging
优先级最低的视图,或者若是全部控件优先级相同,它拉伸第一个视图。
然鹅,咱们只是向他们等距分布就好。切换到Attributes inspector属性编辑器,把Distribution的值从Fill改到Equal Spacing便可:
跑一下看看底部按钮是否是等距分布了,不管是竖屏仍是横盘都是稳稳的,不过还不够完美,当你切换到小屏幕上,好比使用iPhone SE模拟器来跑一下看看。
好在苹果也考虑到这种状况,咱们改变Distribution属性,从Equal Spacing改成Fill Proportionally,spacing值改成10。
如今,在iPhone SE模拟器上再跑一次,此次必须棒棒哒。
咋样,第一次上手stack view
484真香,so easy。
在没有stack view
,你必须使用间隔视图来占位,每对按钮之间有一个占位。要正肯定位间隔视图,您必须向全部间隔视图添加等宽约束以及许多附加约束。 它看起来会像下面这样。为了在屏幕截图中可见,间隔视图被赋予了浅灰色背景:
若是只是偶尔这么作一次其实还好,若是作多了,小伙子身体可吃不消啊。特别是动态添加视图这种。好比隐藏例子中的WEATHER这种。
如今咱们只是简单的设置间距值,若是你想在某个视图中设置特别的间距,在iOS11里提供的新的Api: setCustomSpacing:afterView。
通过上面的演练,下面咱们就能很轻松的把SpotInfoViewController里须要的结构转换成stack view
。
选中评级RATING部分的两个控件。
接着仍是一样的点击Stack按钮将其嵌入到stack view
里。
此次咱们只须要添加三个约束便可:
Top: 20, Leading: 0, Bottom: 20
复制代码
spacing值这是为8
:
你可能会看到一个错位的视图警告,以下图所示,其中星星标签已经超出了视图的范围(这种警告可能由于某些beta版本的缘由才会出现,没出现那就恭喜你继续):
若是肯定本身的约束是正确的,由于Xcode某些版本的bug引发的视图错位,直接用右下角的Refresh Layout按钮矫正便可。
如今看起来就正常了。
若是发现有的时候手残,或者是处于实验性目的,多上了stack view
,直接选中须要撤销的控件,按住Option,左击Stack选Unembed便可撤销。
或者选中控件从菜单Editor \ Unembed撤销也行。
如今咱们来建立垂直方式的堆栈视图,选中WHY VISIT和**<whyVisitLabel>**两个文本控件。
Xcode会根据控件的分布排列来确实方向,就好比如今这样,直接生成的就是垂直分布的堆栈视图。
如今咱们来肯定约束,只须要把这部分的上左右约束都设置为0,只不过底部约束的对象是相对WEATHER控件,间距是20,一看即懂。
设置完后默认对齐是左对齐,以下图所示:
对齐属性肯定堆栈视图如何垂直于其轴布局。对于垂直堆栈视图,能够设置的对齐方式为:
水平堆栈视图对齐属性的值略有不一样:
水平布局的对齐方式分别为:
你们阔以选中刚才设置好的垂直堆栈视图,调整下对齐属性看下变化就浅显易懂了。 填充·Fill:
跑起来看一下布局妥当冇问题。
这部分转换和前面一节没啥区别,直接操做关键点便可。
Top: 20, Leading: 0, Trailing: 0, Bottom: 20
复制代码
设置完之后大概就长这样:
因为须要隐藏天气,因此这部分是比较难搞的。
咱们先把这部分的全部元素都压入堆栈视图。先选中WEATHER文本栏和Hide按钮,压入水平堆栈视图,而后在按住Command选中下面的**<weatherInfoLabel>**文本栏部分,将水平堆栈视图和这部分一块儿压入垂直堆栈视图。
其实能够发现,水平的堆栈视图被Hide按钮给顶开了,若是以为不喜欢,阔以选中底部对齐的方式来看看效果。
也仍是不太满意,那根据个人经验,要不就是修改水平堆栈视图内UI元素的约束优先级,要不就是把Hide按钮给拆出去,单独处理约束。为了容易理解咱们仍是单独处理。
自行撤回到天气部分的原始转态。选中WEATHER和**<weatherInfoLabel>**两个文本栏部分:
将其压入垂直堆栈视图:
而后设置好以下约束:
Top: 20, Leading: 0, Trailing: 0, Bottom: 20
复制代码
对齐方式为填充:
由于Hide按钮被拆出去,因此咱们须要对其添加约束以保证按钮位置的正确性。由于须要设置约束的相对控件为WEATHER文本栏,因此咱们还得再改造改造。 直接在控件列表栏选中WEATHER或使用组合拳Control-Shift-click:
压入堆栈视图:
对齐方式·Alignment选中为靠左对齐·Leading,排版·Axis肯定为垂直·Vertical排版:
运行看看是啥状况:
我顶你个肺,啥状况,按钮跑偏了?其实是咱们拆出Hide按钮以后忘记给设置约束。 按住Control选中Hide按钮拖动指向到WEATHER文本栏添加约束:
只要完成以下两条约束,间距和纵向位置的约束便可:
再从新跑一下,这回就必须稳当了。
在左侧控件列表里选中咱们以前全部作个堆栈化的控件:
所有压入堆栈:
而后给最外层堆栈视图添加约束,确保勾选上Constrain to margins,四边边距约束为0便可。 而后间隙·Spacing设置为20,对齐方式·Alignment设置为填充·Fill。
再次运行仍是会有刚才那个屌问题。
只要记住若是有外设相对控件的约束,只要堆栈化,约束就会被干掉,只能再次添加了:
最后咱们须要把what to see的部分挪动到weather部分上面去,最好的方式是在左侧控件列表里拖动:
若是在Storyboard里直接去拖动,极可能会由于选错控件元素而致使打乱结构。
因为在横屏的状况下,垂直方向上的空间比较珍贵,因此针对横屏,把间隙改成10比较稳妥。 找到间隙·Spacing的左侧的**+**号按钮:
选择Any Width > Compact Height,而后添加·Add Variation:
给wAny hC栏添加值为10便可:
最后运行一下看看,包括横屏(⌘←)也看看,484看起来比较舒爽了。
当前的隐藏和呈现动画效果看起来有木有点生硬,感受怪怪的。咱们仍是添加点动画让细节看起来比较丝滑为妙。 打开SpotInfoViewController.swift,定位到updateWeatherInfoViews(hideWeatherInfo:animated:)
方法,如今看起来长这样:
weatherInfoLabel.hidden = shouldHideWeatherInfo
复制代码
替换成以下代码便可:
if animated {
UIView.animate(withDuration: 0.3) {
self.weatherInfoLabel.isHidden = shouldHideWeatherInfo
}
} else {
weatherInfoLabel.isHidden = shouldHideWeatherInfo
}
复制代码
找到@IBAction func weatherHideOrShowButtonTapped(_ sender: UIButton)
方法,替换成以下代码:
@IBAction func weatherHideOrShowButtonTapped(_ sender: UIButton) {
let shouldHideWeatherInfo = sender.titleLabel!.text! == "Hide"
updateWeatherInfoViews(hideWeatherInfo: shouldHideWeatherInfo, animated: shouldHideWeatherInfo)
shouldHideWeatherInfoSetting = shouldHideWeatherInfo
}
复制代码
这样跑一下看,隐藏起来就不会辣么尬了。。。
一切照旧,懒癌患者或者阅读理解不过关的胖友阔以直接下载最终代码。
有关UIStackView
的使用就到这里,关于使用UIStackView
作高级动画是稍稍有点复杂的,之后有空仍是须要专门开一篇来作介绍。