iOS6 自动布局 入门–Auto Layout

目前为止,即便你的界面设计是在合理的复杂度内,你也必需要为之写许多代码来适应变化的布局。如今我相信你会很高兴听到这种状况将不会发生了-对于iPhone与iPad IOS6 带来了一个很是了不得的特征:自动布局。html

 

自动布局不只能给你的应用带来各类屏幕尺寸设计的支持,作为额外的惊喜,它还能使设计中的各类小事好比多语言环境支持。你今后没必要再为你想要支持的各类语言从新设计nibs和storyboards文件,固然这也包括一些从右至左书写的语言好比说希伯来文和阿拉伯语。ios

这篇教程将向你展现的是如何开始使用Iterface Builder来作自动布局。在iOS 6 by Tutorials里,咱们把这篇教程内容写得更深,而且基于这个知识会有一个全新的章节,在这里面你会看到若是经过代码来释放自动布局的所有功能。spring

好吧,如今开始拿着你喜欢的零食以及饮料,准备开始作一名自动布局的大师吧!canvas

springs and struts 的问题

毫无疑问你可能对autosizing masks比较熟悉–这个也就是 “springs and struts” 模式。autosizing mask决定了一个view会发生什么当它的superview 改变大小的时候。它是否有灵活而且自动修复页边处理能力(the struts),它的宽和高同时也会发生什么变化呢(the springs)?app

举个例子,当一个view的superview的宽度变宽时,它的宽度也会灵活地跟着变宽,而且它的右边界也会自动修复般的一直紧挨着superview的右边界。框架

autosizing 系统处理这种简单的状况仍是不错的,可是当状况稍微复杂一点的时候,它就会很快搞砸你的布局。如今让咱们看一个springs and struts模式所不能处理的一个简单例子吧。编辑器

打开Xcode建立一个基于Single View Application template新项目,把之命名为”StrutsProblem”,选择iPhone程序而且禁用Storyboards:ide

Project options

在 Interface Builder 里点击打开ViewController.xib。在你作任何其余事情以前,请先在nib里把Auto Layout禁用掉。你能够在File inspector里找到这个选项:函数

Disable autolayout

取消选择“Use Autolayout”复选框. 那么如今你的nib使用的是旧版本的 struts-and-springs 模式。工具

提示: 任何你经过Xcode4.5或者更高版本建立的新nib或者storyboard文件会默认使用Auto Layout。由于Auto Layout这个特性只有在IOS 6中有,因此若是你想要使用 Xcode4.5来作一些兼容IOS5的应用,你必需要在新的nib或者storyboard文件中经过取消选择“Use Autolayout”复选框来禁用Auto Layout。

拖拉三个新的view到main view中,如图所示:

Portrait design

为了使看起来更清晰,咱们把每一个view都填注颜色。

如今每一个View都离窗体边界 20 points远;各个填充颜色的view之间的距离也是20 points。底部的view是280 points宽,而且顶部两个view都设置成130 points宽。全部的view都设置成200 points 高。

运行程序而且把模拟器或者你的设备旋转至景观方向。你的设备会以下图因此,和咱们理想的差距甚远:

Landscape looks bad

提示:你可以经过使用 HardwareRotate Left and Rotate Right的菜单选项来旋转模拟器, 或者经过按住Cmd而后使用向左或者向右方向键来旋转。

而我想要的是让程序运行后是这个样子的在景观方向下:

Landscape good

很明显, autosizing masks 对于要达到这三个view的理想变化还须要作点其余的。 从左上角的View来开始设置autosizing :

Autosizing top-left view

这一步使View能紧挨着顶部和左边缘(而不是底部与右边缘),而且在水平和垂直方向上都可以支持伸缩当superview改变其大小时。

相似地, 改变 右上角autosizing 设置:

Autosizing top-right view

这是底部view的设置:

Autosizing bottom view

运行程序而且转动设备至景观方向。如今应该看上去是这样:

Landscape looks bad (2)

和理想的很接近了,可是还有点瑕疵。三个view之间的距离是不正确的。另外仔细看,这三个view的尺寸也不是100%正确. 形成这个缘由是autosizing masks虽然知道要改变view的尺寸当superview改变时,可是它不知道具体该改变多少尺寸。

你能够玩一下 autosizing masks-好比说,改变能够改变的宽和高的值(“springs”)- 可是你几乎不可能精确设置到20-points的距离在三个view之间。

为了解决使用 the springs and struts 方式改变布局所形成的问题,很不幸的,你必需要写一些代码来作。

UIKit 会发送一些消息到你的view controllers当用户界面在开始旋转前,在旋转过程当中以及旋转后。你能够经过监听这些消息来改变你用户界面的布局。一般你会重写willAnimateRotationToInterfaceOrientation:duration: 来改变任何须要从新规划的view的frame。

但在你开始作这以前, 你首先须要声明views里面的outlet 属性。

Xcode切换到 the Assistant Editor 模式(在Xcode工具栏的右上角的编辑器工具包的中间一个按钮)而后把每一个view拖拉至view controller:

Ctrl-drag outlet property

逐个把这些view与属性链接起来:

@property (weak, nonatomic) IBOutlet UIView *topLeftView;
@property (weak, nonatomic) IBOutlet UIView *topRightView;
@property (weak, nonatomic) IBOutlet UIView *bottomView;

Add the following code to ViewController.m:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
                                         duration:(NSTimeInterval)duration
{
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft
    ||  toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
    {
        CGRect rect = self.topLeftView.frame;
        rect.size.width = 210;
        rect.size.height = 120;
        self.topLeftView.frame = rect;

        rect = self.topRightView.frame;
        rect.origin.x = 250;
        rect.size.width = 210;
        rect.size.height = 120;
        self.topRightView.frame = rect;

        rect = self.bottomView.frame;
        rect.origin.y = 160;
        rect.size.width = 440;
        rect.size.height = 120;
        self.bottomView.frame = rect;
    }
    else
    {
        CGRect rect = self.topLeftView.frame;
        rect.size.width = 130;
        rect.size.height = 200;
        self.topLeftView.frame = rect;

        rect = self.topRightView.frame;
        rect.origin.x = 170;
        rect.size.width = 130;
        rect.size.height = 200;
        self.topRightView.frame = rect;

        rect = self.bottomView.frame;
        rect.origin.y = 240;
        rect.size.width = 280;
        rect.size.height = 200;
        self.bottomView.frame = rect;
    }
}

当view controller旋转至一个新的方向时会调用这个回调函数。如今当用户界面的方向转动时view controller使它里面的view尺寸缩放理想了- 这是一种创建在对iPhone屏幕尺寸了解上的硬编码能力。由于这个回调函数发生在一个动画block里,因此当改变它的尺寸会有动画效果。

等等,如今还不能运行程序。 你必须先恢复这三个view的autosizing masks 设置以下图所示,不然 autosizing 机制会与你在 willAnimateRotation: 函数设置里的view的位置、尺寸产生冲突。

Autosizing off

如今能够运行程序了,而后将设备翻转至景观方向。能够看到每一个view的呈现都很理想,再次翻准屏幕至肖像方向,看上去也还不错。

这样作成功了,可是为了这么个简单的呈现你就要必须写许多代码了。想象一下,当你遇到真正更加复杂,特别是动态的那些独立View改变尺寸,或者有一系列的subviews没有被固定时你在代码上所须要做出的努力。

提示: 你还可使用另一种方法,那就是同时作好肖像方向以及景观方向的nib,而后当设备转动时,把对应的view从nib文件载入进来,把当前的view交换出去。但即便这样,你仍是须要作不少的工做,另外你还多了同时管理两个nib文件而不是一个nib文件的麻烦。

Auto Layout 来拯救了!

如今我将要展现的是如何用Auto Layout来作到一样的效果。首先,把willAnimateRotationToInterfaceOrientation:duration:这个方法从ViewController.m里面删除,由于目前我要作的Auto Layout是不须要写任何代码的。

回到ViewController.xib而后在File inspector控制面板里,把“Use Autolayout”的复选框勾上使Auto Layout对这个nib文件起做用:

Enable autolayout

提示: Auto Layout 功能在整个nib或者storyboard文件里老是被开启着的。在这两种文件里的全部view都会使用Auto layout功能若是你把勾选上的话。

如今运行程序而且转动屏幕,呈现的样子仍是以前的混乱样。

Landscape looks bad

如今让咱们启动Auto Layout功能. 按住Cmd键同时选中顶部的两个view (绿色的以及黄色的),。 从 Xcode的Editor 菜单, 选择PinWidths Equally:

Pin widths equally

再次从新选中这两个view而且作 EditorPinHorizontal Spacing操做。 (即便这两个view看上去像被选中了当你作第一个Pin操做后。可是请注意目前他们处在一种特殊的布局关系显示模式中,你仍是必需要从新选中这两个view。)

在左边的文档概要图中, 你会注意到有一个新的section名叫 “Constraints”. 这个section 会被自动加入当你在nib文件中启用Auto Layout时。在这篇文档的下一部分你会了解到这些Contraints是什么以及他们是如何操做的。

如今, 咱们把一个名叫  “Horizontal Space (170)” 的从Constraints列表里面删除:

Horizontal space constraint

运行程序并转动屏幕. 如今看上去好多了 – 顶部的两个view 有了合适的宽度和间距 – 但还不是咱们想要的样子:

Landscape almost there

按住Cmd键同时选中全部的三个view。 在菜单栏, 作PinHeights Equally 操做。

如今仍是按住Cmd键同时选中左上角的以及底部的view,而后作EditorPinVertical Spacing 操做。

最后,把“Vertical Space (240)” 从constraint列表里面删除。

若是你一会儿同时选中全部的三个view,Interface Builder应该以下图所示:

The constraints

蓝色的T型状对象定义了各个view之间的限制。这看上去有点复杂, 可是你一旦学会了,你会发现这种表达至关简洁明了。

运行程序 … 哇, 没有写一行代码每样东西都看上去很是棒了!

Landscape good

酷, 但刚才你究竟作了什么呢?Auto Layout 能使你简单地表达清楚页面布局中的各个view之间的关系而不会让你为了各类view有多大以及他们该定位在哪里硬编许多代码 。

你刚才作了以下的关系操做 – 也就是 constraints – 在页面布局里:

  • 左上角和右上角的view (也就是第一次的pin widths equally 操做).
  • 在左上角view和右上角view之间有20-point的间距 (相应的操做是 pin horizontal spacing).
  • 全部的view是相同的高度 (相应的操做是pin heights equally).
  • 在顶部两个view与底部的view之间有一个20-point的间距 (the pin vertical spacing).

以上这些就足以展现,当屏幕尺寸变化时,Auto Layout如何放置布局里的各类view以及它是如何工做的。

提示: springs-and-struts布局模式也会带来一些其余限制当你从它切换至“Use Autolayout”模式时。对于各个view和屏幕边缘之间的边距都基本会有一条限制,是这么说的:“这个view老是和顶部/底部/左边/右边保持 着20-points的距离。”

你能够看到你的全部contraints在文档概要里。若是你在文档概要里点击一个constraint,Interface Builder会在contraint在view中所体现的地方经过画一条白色的边框而且对之添加一个阴影使其高亮显示:

Selected constraint

Constraints是真实的对象 (属于 NSLayoutConstraint类) ,他们也拥有相应的属性。 好比说,选中顶部两个view间距的constraint(名为“Horizontal Space (20)”)而后切换至它的Attributes inspector。 如今你能够经过修改Constant里的值来改变两个view之间的距离大小。

Constraint attributes

将之设置成100而且运行程序。如今两个view之间的距离更宽了:

Landscape wider margin

当你的程序须要描述各类view的布局时,Auto Layout比起springs and struts表达能力要强许多。在这份教程的余下部分,你将会学到关于constraints的全部以及如何在Interface Builder应用之并使其能作到各类布局安排。

Auto Layout的工做原理

就像你在上面看到的测试同样, Auto Layout 的基本工具就是constraint. 一个constraint 描述了两个view之间的几何关系。好比说,你可能有一个constraint是这样的:

“Lable A的右边界和和Lable B的左边界以20 points的空白相链接。”

Auto Layout用全部的这些constraints来对你全部的view作一些数学计算以至view达到一个理想的位置以及尺寸。 你再也不须要本身来设置view的frame-Auto Layout会帮你作这一切-彻底基于你对view所设置的constraints。

在没有Auto Layout以前,你老是经过硬编码来设置view的框架, 也可能经过Interface Builder 坐标里面精确的放置他们,经过initWithFrame:来传递一个矩形,或者经过设置view的frame,bounds或者center 属性。

对于刚刚你作的应用, 你特意把frames设置到下图所示:

Struts coordinates

你也能够对每一个view作autosizing masks设置:

Struts autosizing masks

那应该再也不是你认为的屏幕设计方式了。使用Auto Layout,你所要作的只是以下图所示:

Auto Layout instead of struts

如今对于view来讲尺寸和位置已经不那么重要了; 把问题都交给constraints吧。固然, 当你在canvas里拖进一个新的按钮或者标签时,这个控件会有一个特定的尺寸而后你把它放到一个特定的位置, 但这也只是一种设计目的来告诉Interface Builder在哪里放置constraints。

设计成你想要的样子

对你来讲一个巨大的优点来使用constraints是你再也不须要摆弄坐标系统来使你的各个view出如今合适的位置。你要作的只是经过对Auto Layout描述每一个view之间的联系关系。这种设计方式咱们叫作 经过目的来设计.

当你经过目的来设计时, 你在表达的是你想要达到的目标是什么而不是如何来完成目标。在之前会是这么个说法:“这个按钮的左上角的坐标是(20, 230)”, 如今你能够这么表达了:

“这个按钮在它的superview中垂直居中,把他放置在离它的superview左边缘的一个固定位置。”

使用这个描述, Auto Layout能自动计算出你的按钮该出如今哪里, 不管它的superview的大小。

这里是其余经过目的来设计的例子(Auto Layout 可以应付全部的这些指示):

“这两个text fields应该保持一样大小。”
“这两个button应该保持同时移动。”
“这四个标签应该同时保持右边对齐。”

这就使你的用户界面设计显得更加具备描述性。你只需简单的定义constraints, 而后系统会自动帮你计算frames。

在第一部分你看到了,要想让一个只有几个view的页面布局同时在iPhone的两个方向显示的合适所须要作到的不少工做。但若是你用Auto Layout来作的话就能够省去那一方面的力气了。若是你对constraints设置的恰当,那么布局会自动恰当显示而不须要你对肖像方向和景观方向的 view作一丝变化。

对于使用Auto Layout另外个重要的好处是国际化。 好比说德文字符, 是出了名的长,把它放进你的标签会是一件十分头疼的事情。 可是再一次,Auto Layout会来拯救你,由于它可以帮你自动缩放基于内容须要表现的标签-除此之外的每样东西仍是会根据constraints来调整。

添加对德文, 法文, 以及其余的语言的支持要作的只是简单设置你的constraints ,translating the text,仅仅是这样哦!

Auto Layout 最好的入门方式就是和它玩。这也就是这份教程余下部分要讲到的。

提示: Auto Layout is 不只仅对方向旋转有帮助;它也能很简单的拉升你的用户界面来适应不一样的屏幕尺寸。这不是一个巧合吗!当iPhone 5的长屏幕出现时这项技术正好被加进了ISO里 了。 Auto Layout 使得你在填满iPhone 5的多余垂直屏幕内容时变得很是简单。而且天知道会不会有一个传言中的 “iPad mini”出现… 至少你如今能够用Auto Layout 来为未来作准备了。

爱上constraints

关掉你目前的工程而后建立一个新的项目使用Single View Application模板。命名项目为“Constraints”。而后选择为iPhone project而且不使用storyboards,可是咱们须要用到ARC。

一个使用Xcode4.5建立的新项目会默认为你选择启动Auto Layout,因此你必要作任何特别的事情来启用它。

点击ViewController.xib 来打开Interface Builder。把一个新的圆角按钮拖进canvas。 注意当你拖拽的时候,蓝色虚线会出现。这些线被认为是 guides:

Guides

这些guides会显示在屏幕的页边, 也会显示在中心:

Other guides

若是你以前使用过Interface Builder,那你毫无疑问会对这些guides很熟悉。当你想要对其东西时他们会很是有帮助。而当Auto Layout 启用时,这些guides有了不一样的意义。你固然仍是须要他们来帮你对其东西,但同时他们也会告诉你新的constraints会体如今哪里。

把button对着guides放到左上角。 如今的nib文件会看上去像这样:

Button with guides

看,有两个蓝色的东西附属在按钮上。 这些 T型状对象就是设置在这个按钮上的constraint。

全部的constraints 也都列在Interface Builder的左边的文档概要面板里:

Button constraints in document outline

目前咱们有两个constraints, 在button和main view的左边缘之间有一个Horizontal Space, 在button和main view的顶部有一个Vertical Space。这层关系被constraint表示为:

“这个按钮会一直待在它的superview的左上角。”

如今再次选中这个按钮并把它放到nib文件右上角,仍是对着蓝色guides:

Button top-right corner

如今 Horizontal Space 的constraint值改变了。它再也不依附在按钮的左边界而是右边界了。

当你对着guides放置一个按钮(或者其余什么view)的时候,你会获得一个标准的大小,这个是被定义在“HIG”里面,这是苹果公司的iOS Human Interface Guidelines文档。对于屏幕的边缘的页边距,标准的大小是20-points的空白。

甚至假设你把button放在某些没有guide的地方,你仍是会获得一个Horizontal or Vertical Space的constraint。试一下。而后把按钮像左挪一点,获得如图所示的效果:

Button larger H space

目前仍是有一个 Horizontal Space的constraint。在文档概要图里,你能看到如今没有一个标准space了。

Larger H space document outline

你的按钮放在哪里,你就会获得一个对应的constraint。

还有一个“center”的constraint.。把按钮拖到canvas的底部中心处,让他正好能卡到中心guides:

Button bottom center

请注意这个Horizontal Space constraint如今被一个Center X Alignment constraint取代了,这也就意味着这个按钮会一直跟着它的superview中心对其在水平轴上。依然有一个Vertical Space constraint值保持着这个按钮待在view的最底部。(仍是请使用标准页边距)。

运行程序而且转动设备至景观方向。看,甚至在景观方向,这个按钮仍是呆在底部的中心位置:

Button at bottom center in landscape

对于这个按钮,这是你想要表达的目的是: “这个按钮应该一直待在底部的中心位置。” 请注意,如今没有任何地方你必需要告诉Interface Builder你的按钮的坐标是什么, 你只要把它放置的view中就好了。

有个Auto Layout,你能够不用在关心你的view在canvas里面的精确坐标位置了。全部这一切,Auto Layout会帮你从你设置的constraints里面派生出来(或者说是Interface Builder为你设置了这一切)。

在这个范例里你能够看出这个按钮在Size inspector里面的转化,那是至关的大啊:

Different size inspectors

当Auto Layout 禁用时,在X,Y,Width或者Height里的值会改变所选中view的位置以及尺寸。当Auto Layout 启用时,你仍是可以在这些框里面输入新的值,但一般结果不会你是想要的效果。那个view 会移动,可是Interface Builder也会基于你的新值来计算出新的constraints。

好比说,把Width的值改到100,canvas里面的按钮会变成下图这个样子:

Button with fixed width

如今 Center X Alignment constraint的值消失了, 取而代之的是一个把按钮连在屏幕左边缘的Horizontal Space,这个按钮同时也会产生了一个新的constraint,它强制使按钮的宽度固定在100 points(能够看到按钮下方的蓝色栏)。

你在文档概要图的左边看到如今有了一个新的Width constraint:

Width constraint document outline

不像其余的constraint,那些是在按钮和它的superview之间,这个宽度constraint只能应用于按钮自己。你能够认为它是一个按钮和按钮之间的constraint。

拖动按钮使它再次卡在 Center X Alignment constraint 上。

小贴士: 由于经过 Size inspector来改变位置和大小可能会搞乱你的constraints,我建议尽可能不要这么作,若是你非要改动布局,请更改constraints。

你如今可能想知道为何按钮以前没有一个Width constraint。在没有的状况下,Auto Layout是如何知道要改变按钮的长度的呢?

能够这么解释:这个按钮自身知道他的宽度应该是多少,它经过基于它里面的标题文字外加上一些圆角的边距填充,能够计算出来的。若是你设置了一个按钮的背景图片,它也会把这一点计算在内的。

这个现象被认为是固有内容尺寸。不是全部的空间都会这样,可是大部分是这样的(UILable不在内)。若是一个view可以计算出它本身的首选尺寸,那么你就没有必要对其专门设置Width or Height constraints 了。关于这个之后你就看得多了。

为了获得按钮的最佳尺寸,选中它而且在Editor菜单里将至设置为Size to Fit Content 。这步操做会使按钮摆脱明确的Width constraint 而且将之恢复为按钮的固有内容尺寸模式。

两个按钮的探戈

Guides 不只能够出如今view与superview的, 也能够出如今同一阶层的多个view之间。为了证实这点,如今请在canvas里面拖进一个新的圆角矩形按钮。

若是你把这个按钮放得离另一个比较远,这个按钮回获得本身的constraints。然而,若是你把两个按钮放的足够近,那么这两个按钮的constraint会开始互相做用。

把新的按钮捕捉到原来按钮的旁边:

Snap two buttons

如今这里会出现一些点状guidelines,但Interface Builder不会把他们所有转换成constraint;由于这有一点多了。但这基本会认出这两个按钮能在各个方位对齐-在他们的顶部,中心以及基线处。

在把新按钮放下后,这个按钮的constraints会看上去像这样:

Two buttons

如图所示,新的按钮有一个Vertical Space对于屏幕的底部,也有一个Horizontal Space对于另一个按钮。可是这个space是很是小的(只有8points),T型状对象可能很难看到,但必定是存在于那里的。

在文档概要图中选中Horizontal Space constraint :

Highlighted H-space between buttons

当你选中一个constraint的时候,它会在屏幕中属于它的地方高亮显示。这个显示在两个按钮之间特别的constraint ,它的意思是在说:

“第二个按钮将会一直出如今第一个按钮的右边,不管第一个按钮的位置以及大小如何变化。”

选中左边的按钮而后输入一些字好比说“A longer label”。你会看到当新的标题输进去之后,左边的按钮从新设置了其尺寸,而且另一个按钮也移出了它原来的位置。可是它始终是附属在第一个按钮的右边边界,这也就是咱们想要的结果:

Button with longer label

请注意Interface Builder从新用一个Horizontal Space代替了原来的Center X Alignment。每次当你对控件作一个尺寸的(或者位置)的改变,Interface Builder会计算出一个它认为对的constraint。一般来讲,它都是对的,但有时候它会彻底误解咱们的意思。在这里,你明显想要将按钮保持在中心位置当你在改变其中的文字时。

把按钮从新放置到它的中心对齐处去。看看如今的constraint是怎么样的:

Two buttons disconnected

这可能不是你想要发生的。如今两个按钮之间再也不互相链接了。取而代之的是,新的右按钮和屏幕的右边缘有了一个Horizontal Space的constraint。两个按钮之间没有Horizontal Space了。

固然,你能够经过把捕捉在一块儿而后再将他们从新链接,但这个问题是能够经过不拖拽view来避免的。

首先,经过快捷键Cmd-Z来取消操做,使第一个按钮再也不中心对齐。如今选中按钮而且在Editor 菜单选择 AlignHorizontal Center in Container。此次不只是第一个按钮移到了屏幕的中心处-另一个也跟着移了过来。更可能应该这样操做吧!

为了可以对之概念有更好的了解,仍是多作一些操做吧。选中小的按钮而后把它放到大的上面去,这样以来他们被捕捉进了place vertically(但不要尝试对齐这两个按钮的左边缘):

Button on top

由于你把两个按钮捕捉在了一块儿,因此如今他们之间有一个Vertical Space。这个间距依然是由HIG推荐的8 points远。

提示: 这个 “HIG”, 是 iOS Human Interface Guidelines的简称, 介绍了苹果对设计优秀的用户界面推荐设置。对于IOS开发人员来讲是必读的.。HIG 解释了在哪一种状况下选择哪一种UI元素是合适的,而且提供使用他们的最好实例. 你能够在这里查看它。

你能够对于控件之间的标准距离不受限制。constraint是彻底成熟的对象,就像view,因此你也能够改变其属性。

选择两个view之间的Vertical Space constraint。你也能够经过点击T型状对象来作到,尽管这有点太过讲究。但目前为止最简单的方式仍是点击文档概要图里面的constraint。一旦你选中了,切换到Attributes inspector:

V-space attributes

默认的Standard attribute的勾是选上的。对于两个对象之间的space constraint是8 points;对于一个view于之superview之间的边缘距是20 points。在constraint框里面输入40来改变其constraint大小。看,如今两个按钮离的更远了,但他们之间仍是链接着的:

V-space larger

运行程序来看看效果:

V-space larger landscape

按钮之间明显保持着他们的垂直距离安排,可是他们的水平方向却没有!

若是你仔细看nib文件,你会发现上边的按钮和canvas的左边缘之间有一个Horizontal Space(若是你像我同样在同一个点粗糙的放置了那个按钮的话):

H-space anchoring top button

底部的标签在屏幕中水平居中对齐,但上边的按钮不是的-它老是和左边缘保持着同样的距离。

这看上不是很理想,其实你想要的结果是以下目标:

“底部按钮应该一直保持水平居中,而且顶部按钮左边界要一直对齐着底部按钮的左边界。”

对于第一中constraint,你已经拥有了,可是第二种你尚未。Interface Builder 会显示对齐的guides, 因此你可以向左拖拽上边的按钮直到它的边界捕捉到下边的边界:

Snap left edges

不幸的是,这个操做移出了两个按钮之间的Vertical Space(至少在有些时候,这取决于控件是如何拖拽以及放置的操做)。Interface Builder根本“忘了”那曾经有一个Vertical Space,取而代之的操做是于底部的view又从新生成一个Vertical Space:

Two buttons left aligned, wrong V-space

这和你想要的结果差的太远了。结果不该该是在两个按钮之间有一个Vertical Space 吗?而不是窗口的底部产生一个Vertical Space。

相关文章
相关标签/搜索