按照计划,这篇文章将是这个系列里的最后一篇了。
在上一篇文章中,为了让最后的三个第三方登录按钮的间距能够根据屏幕的宽度自动调整,我先添加了一个组,再在组里面添加约束,弄的很复杂,而且这种方法也有一定的局限性。
我在上篇文章了就讲过,这个问题有更简单的解决方案。这个东西叫做StackView,在我之前讲过的添加约束的方式中,第一个按钮就是。
它可以让你不用添加约束就能使用Autolayout里的很多功能,以后维护起来也会更方便。和上篇文章讲的一样,先拖出三个按钮放好,这次不用给他们先放到一个组里,只要三个一起选中后,点击上面说过的Stack按钮,就将他们放进了一个StackView里了,你可以理解为对它们进行了编组。
编组后发现三个按钮变成垂直排列的同学先不要急,后面我会讲到如何把它们变成水平分布的。这样我们就将它们都放到了一个组里了,接下来先给这个组添加约束,和之前用的方法一样。组的宽度还是设置为屏幕宽度的0.6倍。添加完成后变成这样了。
但是里面的按钮并没有和我们想象的一样平均分布,在上篇文章中,我们添加了很多约束,将这些按钮固定在了组里的某些特定的位置。你也可以在StackView里面添加约束,但是这里我们完全没必要这么做。我们只要选中整个StackView,就能在右边栏看到它的属性了。只要修改一个选项就能达到我们要求的效果。
下面我就解释一下这些选项代表的是什么意思。
第一个: Aixs 定义的是这个组的分布方向,我们三个按钮是水平分布的,所以这里不需要修改,如果你编组后他们是垂直分布的,只需要在这里将它们改成Horizontal就行了。
第二个 :Alignment 定义的是组内元素的对齐方式,你可以在这里设置上对齐,下对齐之类的,因为这三个按钮大小是一样的,所以对齐方式也无所谓了,使用默认的就行。
第三个:Distribution 定义的是他们的分布方式,我们只要在这里选择equal spaceing 就能让他们平均分布了。
第四个 : Spaceing 是用来定义相邻元素之间的距离的,你可以在后面的输入框中输入你想要的数值。
修改好了Distribution后,我们的工作就完成了。
StackView的威力不限于此,假设现在产品经理屁颠屁颠地跑来和你说,我们又多了一个第三方登录的渠道,需要加上去。如果你使用的是我在上篇文章中的做法,那么现在你必须从头来过,而且那种将三个按钮放在最左,中间,最右的做法也完全失效了,必须得想出新的办法来。
而如果你使用的是StackView,那这个问题完全不叫什么问题,你只要从控件库里面拖出一个新的按钮,直接扔到这个StackView里面就行了,其他的东西都是自动帮你搞定的。
再讲一个StackView的实际应用,假设我们设计了这样一个页面,想象一下,如果你一个个的去添加约束的话,会是一件多么麻烦的事情,而当需要在中间在插进一行新的内容的时候,那会让你更加痛苦。
而如果你使用的是StackView的话,这一切都变的非常简单。首先你将左边的一整列都放进一个StackView里面,这时候的Aixs应该是Vertical,在Alignment里将对齐方式改为Trailing(尾对齐),然后Spaceing里面调整一下行间距就可以了。
用同样的方式将右边的文字也都放进一个StackView里面,Alignment里设置Leading(首对齐),将Spaceing里的数字调整到和左边的一样。
最后将左右两个StackView再放进一个StackView里面,根据需要在Spaceing 里面调整它们之间的距离。将这个总的StackView放到你想要的位置就完成了。要添加新的一行,只需要将它们拖进之前设置好的StackView里就可以了。
StackView背后使用的也是AutoLayout,所以你还可以在StackView里面添加约束,做出更复杂的页面布局。
事实上苹果建议你将StackView作为一个最基础的元素来构建你的整个页面,因为它实在是太方便了。
约束的优先级 Constraint Priorities
我在之前讲过,只有当能从你给的约束关系中推断出位置和大小信息,而且还没有冲突时,才能通过。
在现实开发中,有可能会出现约束之间冲突的情况,这时候我们该如何处理呢?实际上不是所有的约束都是必须满足的。还记得我在上篇文章中讲过的双击修改约束吗?双击约束线后会弹出这样一个Popup,其中第二行的Priority 就是这个约束的优先级。
你可以给约束设定一个优先级,从0到1000,默认约束的优先级为1000,也就是说是必须满足的。但如果你将优先级调整到0到999之间,那就意味着这个约束并不是必须满足的,而是根据实际情况来取舍。当出现冲突时,AutoLayout会根据Priority数值的大小来选择优先满足哪些约束,数值越高,就越优先满足。
可是我们不该在一开始就避免去设置有冲突的约束么?如果我们一开始就去避免这个问题,那优先级还有什么用?
下面我讲一个例子来演示一下约束优先级的实际应用。
假设我们在做一个软件,在这个软件里我们给出了两种基本的操作:打赏 和 支持。
规则是这样的:打赏就是你给这个作者一定的虚拟币,每个用户可以进行无限次数的打赏。
支持,则更多的是精神上的自持,每个用户对于某个特定的观点只能支持一次。
通过以上的描述我们可以设计这样两个按钮:
因为支持按钮只有一次点击机会,所以当支持按钮点击过后它就变成不可点击状态,它的使命也就完成了。
但是,既然“支持”这个按钮点过以后就失效了,为什么不将它拿掉不显示呢。可是如果去掉支持按钮,那么和支持按钮相关的约束都没有了,打赏按钮的宽度是没有被定义的。该如何来解决这个问题呢?
答案就是再创建一个约束,将打赏的尾部和屏幕最右边的距离设置为10 。这样打赏按钮的尾部有了两个约束了,一个说我要和支持按钮保持10的距离,一个说我要和屏幕的右边保持10的距离,显然这两个约束是冲突的。解决这个冲突的办法就是将新加的约束的优先级降低。在下图我用虚线表示。
这样初始状态时,因为第二个约束并不是必须满足的,所以一开始是被舍弃的。但是当支持按钮被移除后,这个新加的按钮正好能派上用处。这样页面就变成了这样:
约束不一定是固定值
前面我讲的约束都是一个固定的数值,但实际上着并不是必须要这样的。你可以设置他们之间的关系,大于等于某个值,等于某个值,小于等于某个值。再看一下修改约束的Popup,第一个选项就是让你选择这个关系,只不过默认的是等于。
下面再看一个实际情况。
假如我有这样一行内容,前面是描述,后面是内容,我们规定了它们各自离开屏幕两个边的距离。但是我们并不是十分关心它们之间的距离,所以我们可以不设置它们之间的约束,让他们根据显示的内容自动调整好了。然而,当后面这个交易编号变的特别长的时候,就会出现文字叠加的情况。所以为了保证它们不重叠,我们还是需要在他们之间设置一个约束,如规定它们的距离必须大于等于10。这样大多数情况下能保证这两个label还是能自由伸缩,而且不会出现重叠的情况。当编号变的特别长时可以触发新的适配机制,如让编号的字体缩小,而不是直接重叠到前面的标题上去。
Auotresizing
不得不承认的是,有时候设置约束是一件很麻烦的事情,特别是你面对的是复杂的界面的时候,而有时候,你还没想好要设置成怎么样,只是想先试试。这时候你就可以试试苹果推出的新功能,前提是你要把你的Xcode 升级到8.0以上。
这个功能就是Auotresizing,它让你不设置约束就能快速验证你的想法。它使用起来也非常简单,在选中你要设置的视图的前提下,当你选择左边栏中的标尺icon 后就能看到Auotresizing功能了。
能看到中间的正方形四周有四个约束,虚线状态下表示这个约束没有添加,当你点一下后,它就会变成实线,表示已经添加上了,而中间的两个带有箭头的虚线则代表是否允许伸缩。默认是不允许的,如果你点击宽度方向的以后,这条线就变成了实线,表示宽度方向是可以自由伸缩的。边上还会有一个小动画来告诉你这些视图会怎么变。有兴趣的可以去尝试一下。
到这里,这个系列的文章就算结束了。当然我这个系列的文章里不可能提到所有和AutoLayout的知识。很多人看完以后可能也就忘了如何去添加约束,但是我觉我写这个系列的文章,最大的目的不是让你看完以后能像程序员一样去开发自己设计的页面了,而是让你了解这种相对布局的思想。希望看完这一系列文章后,当你再次看设计稿时,能有一种新的视角。
Via: