IOS 6 自动布局 入门 2

来自Ray:恭喜各位!大家已经经过宣传ios feast提早解锁了第一个有关IOS6的教程。 ios

目前这份教程只是咱们的新书iOS 6 By Tutorials里面某个章节的精简版。这份教程由一样著做过iOS Apprentice Series的Matthijs Hollemans 完成,开始体验吧! 程序员

这份教程由IOS 教程小组的组员Matthijs Hollemans发布,Matthijs既是一位经验丰富的IOS程序员又是一名资深老到的界面设计者。. spring


这系列教程的第一部分你见识到了旧的“struts-and-springs” 模式不能简单的解决全部的用户界面布局问题。新的IOS 6特征是一种解决方案,但由于这个技术是如此的有效,它使用起来仍是有点小棘手的。在这系列教程的第二部分也是最后一部分, 你将继续学习constraint的概念以及如何运用他们! canvas

大胆尝试constraint

也许你已经注意在canvas里面到有些T型状对象看上去比其余的要粗一点。这些加粗的,咱们称之为user constraints,你删除它们后的效果和删除细的是不一样的。当你删除一个user constraints,Interface Builder常常会自动在删除的地方放置一个不可删除的constraint来代替之。我立刻就会讲到为何会这样。
在文档概要图中,user constraint有一个蓝色按钮: xcode

User constraints document outline

 

选中 Vertical Space (40) constraint 而后按一下键盘上的删除按钮。 在两个按钮之间的T形状对象消失了,取而代之的是一个新的直接链接屏幕底部的Vertical Space constraint : app

After deleting user constraint

新的constraint有一个紫色的按钮,而且图中它的线没有被加粗,这也就表明着它是不可删除的。如今这两个再也不在垂直方向链接在一块儿了。尽管因为Leading Alignment constraint 而依然左边对齐着。
为何会发生这种事情? 为何 Interface Builder对按钮发出了一个新的 Vertical Constraint , 甚至你尚未告诉它要删除这么一个constraint?答案是: iview

对于每个view都必需要有足够的constraints来对其进行位置以及大小的控制。 dom

当用到 Auto Layout时,这是一条最重要的规则。若是对于一个view没有足够的 constraints, 它的 Auto Layout 将不能决定它的位置以及大小。 这种布局是被认为无效的。待会你会看到几个无效布局的例子。 ide

Interface Builder会尽可能帮你避免布局无效。这两个按钮的尺寸是能够知道的由于他们根据他们包含的文本,背景图以及其余的一些东西-固定尺寸内容是能够肯定下来他们的尺寸,还记得不?因此这不会是一个问题,上方按钮的X-位置也能够经过它的左边界与下方按钮的左边界对齐来获取,而下方按钮又一直保持着底部居中。如今惟一不肯定的就是它的Y-位置。 工具

以前的话,这两个按钮用一个 Vertical Space相连。这个条件足够能推导出上方按钮的Y-位置。但若是你删除了Vertical Space,上方按钮就没有依据来定位它在view里的垂直位置了。由于Auto Layout不知道如何决定它的Y位置,因此它不能在屏幕中显示出来。

为了不这种状况发生,Interface Builder须要从新在view中找一个离按钮底部边界最近的地方“pin”它。

Pin all the buttons

有趣的是,当你从新运行程序而且转动屏幕至景观方向时,仍是以前的效果嘛。这也是正常的,但你的设计确实从根本上就不一样了:这两个按钮如今都与窗体的底部相连。这也就意味着,当下方按钮移动时,上方的按钮不会跟着它一块儿动了。(注意这个解决方案也不算很好,好很差取决于和你理想的效果是否相同。在这个例子中,你明显是但愿这两个间有一个vertical connnetion。)

咱们证实一下,选中底下那个按钮的和屏幕底边的一个Vertical Space constraint,而后到Attributes inspector ,它的常量如今是“Auto”,目前它是一个标准尺寸,如今把它改成40。
由于这两个按钮选择没有连接,因此如今只有下方的按钮往上面移动了;上方的按钮仍是保持原位:

Only bottom button moves up

注意当改变 constraint常量值时会将它提高为一个 加粗的 “user” constraint。

针和销

如今让咱们把两个按钮在再次链接在一块儿。目前为止你经过把按钮拖进canvas来获得了一些constraints,你能够在稍后作这些。按住Cmd键而后同时选中它们,在Editor菜单, 而后选择PinVertical Spacing。

你也能够经过右下角的小面板菜单来作这个constraint:

Shortcut menu pin

它会弹出以下菜单:
Pin menu

 

先无论你选择了哪一种方法, 这个操做在两个按钮之间添加了一个新的constraint:

Pin vertical spacing

这个新的constraint是一个有常量为20 points的Vertical Space 。这仅仅是由于当你把两个按钮链接起来的时候,他们之间的距离是20 points。

注意原来从上方按钮到屏幕底部的Vertical Space仍是存在的。这个constraint是Vertical Space(104)- 如今已经不须要,因此删了它吧。

以前当你删除一个蓝色constraint的时候,一个紫色会出现而且取代它。如今这种事情不会发生了,由于剩下的constraints已经足够表达清楚全部view的位置。只有在现有constraint不够的状况下,Interface Builder才会添加新的constraint。

如今你的constraints应该以下所示:

Restored constraints

选中底部的 Vertical Space (经过在canvas上点击) 而后把它的constant 40的值改回为标准值。这步不只仅应该把下方按钮往下移,上方的按钮也该移动。由于如今他们又被链接在一块儿了。

一个动态运行小测试

如今你知道的一点基础知识有:如何使用guides来放置控件,如何使他们相连对齐,如何在空间之间设置空白空间。在这篇教程后,你也会了解到Align and Pin 菜单的其余选项。

使用Interface Builder 来鼓捣constraints是很是不错的, 但如今让咱们来看看,在程序运行的时候这个是如何工做的。在?ViewController.m 中加入以下方法:

- (IBAction)buttonTapped:(UIButton *)sender { if ([[sender titleForState:UIControlStateNormal] isEqualToString:@"X"]) [sender setTitle:@"A very long title for this button" forState:UIControlStateNormal]; else [sender setTitle:@"X" forState:UIControlStateNormal]; }

这个方法解释为经过触发按钮事件来简单的切换按钮标题的长短。从Interface Builder里面给这两个按钮链接方法:对每一个按钮按住Ctrl拖至File’s Owner 而后在组里面选择buttonTapped:

运行程序看看这会怎么样。而且同时在景观方向和肖像方向设置测试。

Long and short titles

不论你触碰的是哪一个按钮,如今的页面布局老是可以符合你提出的contraints:

  • 在水平方向,下方的按钮老是在窗口中水平居中。
  • 下方的按钮老是和窗口的底部保持20 points距离。
  • 上方的按钮老是和下方的保持左边界对齐。

这是你设置的整个用户界面的规范。

你能够为了乐趣,同时在Interface Builder选中两个按钮,而后从Align菜单选择Right Edges。而后运行程序注意观察这其中的区别。

重复地,但如今请选择AlignHorizontal Centers。这会使上方的按钮中心和下方的按钮的中心对齐。如今运行程序看看这些按钮是如何工做的。

修复宽度

Pin 菜单有一个 Widths Equally选项。 若是你的两个view设置了这个constraint,那么Auto Layout 会一直保持两个view的宽度相等,这个宽度值取决于较宽的那个view。让咱们来对这个作一个实验。

选中这两个按钮而后在菜单里选择?PinWidths Equally。?这步操做为两个按钮添加了一个新的constraint:

Buttons widths equally

提示: 若是两个按钮的任意一个与superview有一个你不想要的constraint,那么请再次同时选中两个按钮而后执行 AlignHorizontal Centers选项。

在这系列教程的第一部分,你实际上是已经见识过了这类constraint。这个看上去和普通的T型状对象相似,但其实在这T型状对象的中间有一个圈,圈里是有一个等于号的。

看,在文档概要图里又多了一个 ?Equal Widths constraint:

Equal widths in document outline

如今改变其中一个按钮的标签内容也会同时改变到另外个按钮的尺寸了。

把下方按钮的标签内容改至 “X”,让它足够小。你能够注意到上方按钮的尺寸不在兼容它的内容了:

Top button text no longer fits

那么Interface Builder是如何知道要选用哪一个按钮的尺寸的呢? 若是你足够细心的话,你会发现有一个, Width constraint 被加到了上方按钮:

Width constraint on truncated button in document outline

Width constraint on truncated button

Interface Builder 强制上方按钮变小,为了知足Equal Widths constraint这个限制条件。

很明显这不是你想要的结果,因此请选择上方按钮而后在Editor菜单里为它选择Size to Fit Content(或者按快捷键 Cmd =)。如今,按钮里面的文本又能所有看到了 –  或者更科学的说,这个按钮可以根据包含的文本而调整大小了 – 另外它的Width constraint也消失了。

运行程序而后点击按钮。如今两个按钮一直保持相同宽度了,不论哪一个按钮的长度比较宽:

Buttons equal widths in app

固然当两个按钮都变得很是短时,他们仍是会一块儿缩小到相等宽度。除非有个constraint来作限制,否则的话按钮控件是会根据他本身包含的内容来很少很多的调整本身的尺寸到一个恰当的大小。这个叫什么功能呢?对的,这就是固有内容尺寸。

固有内容尺寸

在 Auto Layout功能出现以前, 你一般会设置你的各类控件该有多大,或者在经过定制他们的frame、bounds属性来改变大小,或者直接在Interface Builder来改变他们的大小。 但目前的状况是大部分的控件彻底有能力基于它们的内容来计算出自生所要占的空间大小。

一个label可以经过设置在它上面的文本长度以及文本字体来计算出本身的宽和高。相似地,button,能够经过在它带有背景的文本以及一些圆角的填充来计算出适合本身的宽和高。

这也适用于不少分段控件,如一些progress bars,还有许多的其余控件,尽管有一些是有一个预约义的高,可是它宽仍是能够设置的。

这就是所谓的 固有尺寸内容, 在Auto Layout这是一个重要的概念。在按钮的操做中你已经见识到了吧。. Auto Layout 会先问你的空间他们有多大,而后在基于空间给出的信息将他们展现到屏幕上去。

你也能够不使用它,但你要明确设置这个空间的Width 或者 Height constraint。若是你这么作了,那么 Interface Builder 为自动生成一个你设置的constraint。若是想要再次恢复固有内容尺寸的话,你只需从新使用Size to Fit Content 操做, 另外以前你设置的 Width or Height constraints会自动消失.

一般来讲,你使用固有内容尺寸功能就够了,但有些状况下这功能仍是尽如人意的。想象一下,当你须要在UIImageView上设置一个image的时候,若是那个image要比屏幕大的多,你一般会给image设置一个合适的宽度以及高度来适应UIImageView的内容尺寸,除非你想让imageview来自动帮你从新设置image的dimensions。

若是对一个按钮设置一个固定的 Width constraint,状况会怎么样? 虽然按钮可以计算本身的尺寸,可是你能经过给他设置一个固定的尺寸来使它的计算无效。选中上方的按钮而后在菜单选择PinWidth。 看,按钮上方有了一个固定的T型状对象了:

Button fixed width constraint

由于这类的constraint只应用于按钮自己,而不是它的superview,它被列在文档概要图中的按钮对象下方。就像你刚才所作的,如今这个按钮的固定尺寸被设为了73 points。

运行程序而后点击按钮,看看发生了什么?按钮的文本内容改变了,它再也不所有显示内容了由于缺乏足够多的空间:

Button text clipped

由于上方按钮有个固定的尺寸又由于两个按钮被要求是同一尺寸,因此他们不会再缩小和放大了。

提示: 你一般的设计理念是不会对一个按钮设置Width constraint – 最好的状况是让按钮使用它本身的固有内容尺寸 – 但当你遇到过一个你但愿控件自动改变尺寸而它没有改变的布局问题时,那么最好请屡次确认一下Interface Builder里面有没有一个固定的 Width constraint。

仍是多玩一会这个东西吧以便于你真正掌握 对view对象的pinning 以及aligning 。由于不是全部的现象都很明显,因此你最好对它有一种感受。可是请你记住,对于必需要有足够多的constraints,  Auto Layout 才能对全部的view判断出位置以及尺寸。

Got enough constraints

图库实例

如今你应该对constraint是什么以及知道如何在不一样view之间创建关系来构造你的布局。 接下来,你将会看到如何使用 Auto Layout 以及 constraints 来创造一个符合现实世界场景的布局。

假设你要制做一个关于你最喜欢的程序员的图库应用,在景观和肖像方向,它看上去应该以下图所示:

The Gallery app

这个屏幕如今被分红了4块大小相同的部分。每一个部分有个imageview以及一个label。你怎么样来作到这个呢?

让咱们从新开始这个程序。你可使用你现存的“constraints”项目经过把里面的按钮所有删光。

或者,你能够从新建立一个新项目,用 Single View Application 模板而后你随便给他取一个名字你喜欢的名字。好比说,“画廊”。这里面只须要使用nib文件,因此请禁用掉storyboards 选项。

从对象库打开ViewController.xib文件, 把一个普通的view放到canvas上。把它的宽设为160 points,高设为230 points, 而后把背景改成你喜欢的某种颜色 (我把它改成绿色):View with auto layout

这个view在它的空间内有4个constraint。不像一个button或者label,一个普通的UIView 没有固有内容尺寸功能。因此它必需要有足够的constraints来断定它的位置以及大小,因此如今这个view须要constraints来决定它须要的尺寸大小。

你可能想知道,这些尺寸的constraints在哪里?在这种状况下,这些view的尺寸经过他们superview的尺寸来获得。在这个布局中,有两个Horizontal Spaces 以及两个Vertical Spaces,而且这些都有固定尺寸。你能够在文档概要图中看到这些:

Constraints for UIView in document outline

绿色view的宽度能够经过这个公式 “superview的宽度 减去(109 + 51)” 来计算获得,相似的它的高度能够经过 “superview的高度 减去(153 + 77)”。 由于这些空白constraints被固定了,全部view自己没有机会来改变大小。但当你转动应用时,superview的尺寸从320×460变为480×300。把这新的宽度以及高度放到公式中,你会获得一个新的绿色view的尺寸。

你能够经过运行程序而且转动至景观模式看到这个现象,但你也能够直接在 Interface Builder里直接模拟这种状况。

选择nib文件里最顶层的view 而后到 Attributes inspector里去看,在 Simulated Metrics 部分里, 把方向改成景观模式:

Simulated metrics landscape

这里能够看到 nib 文件在景观方向的直接布局现实。这个绿色view为了要知足 Horizontal and Vertical Space constraints 而从新改变了它的尺寸。

再切回到肖像方向。

提示:如今有两个理由解释在nib文件上你为何要用一个普通的UIView : a) 你将要用它来作其余view的容器,使用它能够帮助你组织你nib文件的内容。; b) 这对于一个定制的view或者control来讲是一个占位标志,你能够把它类属性设置为你本身写的 UIView或者 UIControl的子类。

有时当设备转动时你不是总但愿你的UIView 从新改变大小, 因此如今咱们经过 constraints 来定制view的固定宽度/或者高度。咱们来动手作一下。 选中绿色view而后在 Pin 菜单, 选择Width。一样地再次选中绿色view而后在菜单里选择 PinHeight。

你如今能够对view添加两个新的constraint,一个160 point的Width constraint 和一个230 point Height constraint:

Width and height constraints on UIView

由于宽度和高度只适用于这个view,在文档概要图中,他们处在view自身的目录下。一般来讲,cnostraints只表现为两个view之间的关系 – 好比说,在绿色view和它的灰色superview之间有 Horizontal 和 Vertical Space constraints 这个关系 – 但你也能够认为 Width 和Height constraints 是view和它自身的关系。

如今运行程序。恩!在肖像方向看上去不错。 如今把view翻转至景观方向。擦! 它的样子不只不是你想要的 – 它自身的尺寸又改变了 – 并且Xcode也报了一个使人讨厌的错误信息:

Gallery[68932:11303] Unable to simultaneously satisfy constraints.  Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "", "", "", "", "" ) Will attempt to recover by breaking constraint    Break on objc_exception_throw to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

是否还记得我说过对于view来讲必需要有足够多的constraint,那么Auto Layout才能计算出全部view的位置以及尺寸?那么,如今这个例子的状况是它有太多的constraints了。不管什么时候当你获得错误 “Unable to simultaneously satisfy constraints”时, 这在暗示你的constraints在某些地方起冲突了。

让咱们再来看看那些contraints:

Conflicting constraints

对于这个绿色view,目前有6个constraint。四个以前你见过,另外两个新的 Width 和Height 是你刚加上去的。那么冲突起在哪里呢?

那么, 在肖像模式中数学的计算是没有问题的。superveiw的尺寸是320 points。若是你把绿色view的宽度再加上Horizontal Space的长度,那么你应该获得320这个值。我定位绿色view的方式是:51 + 160 + 109 = 320。相似地,垂直vertical constraints 应该加到 460。

但当你转到设备至景观模式时,主窗口 (也就是它的superview)是 480 points 宽。这意味着 51 + 160 + 109 + ? = 480。 在这等号的左边还须要一个160 points可是Auto Layout殊不知道去哪里获得它。相似地,垂直坐标也是这个状况。

如今咱们遇到的冲突为如下两种状况中的一种,要么view的宽度是固定的可是它对应的页边必须是能够改变大小,要么它对应的页边是固定的可是它的宽度能够改变大小。 在上面的例子中,你想要这个view在两个方向保持相同的宽度,因此后面的Horizontal Space 必需要删除掉。

把右边的 Horizontal Space删除以及把底部的Vertical Space删除。如今 nib 文件应该看上去这样了:

Conflicting constraints fixed

如今这个view已经有恰当数量的constraint来决定它的尺寸以及位置。很少也很多。再次运行程序,能够看到xcode报错信息已经没有了,这个view也在屏幕转动后保持了相同尺寸。

提示: 尽管 Interface Builder 已经很努力的帮你避免掉无效的布局了,可是它不是万能的。 但是至少Auto Layout会为你报出一个详细的错误信息当你有些设置是错误的时候。 在 iOS 6 by Tutorials这本书里的”Intermediate Auto Layout”你能够学到更多关于如何分析错误信息以及如何诊断布局问题的介绍。

把肖像画出来

在绿色view中拖进一个label。 注意如今的guides是在绿色view中出现了,由于它是label的superview。

Drag label into green view

根据guides把label放到绿色view的左上角。这会给label在绿色view中添加两个 Space constraints 来定位本身:

Label constraints

注意这两个新的 Horizontal and Vertical Space constraints 是被列在绿色view的contraints目录下面而不是main view下。

如今稍微把绿色view移动一点。你能够看到只有在绿色view和它的superview之间constraints改变了。而不是label的那些。 这个label会根据绿色view一直待在同一个相同的地方。

选中label而后把它移动到绿色view的底部边缘,并使它中心对称。而后在nib里拖进去一个新的imageview,使布局看上去以下图所示:

Image view in gallery

把这imageview固定在顶部,以及它superview的左右两个边界。但它的底部是经过一个标准spacing与底部标签相连。

下载 这份教程的素材 而后解压文件。在里面你会找到一个 Images 文件夹 – 把它加入到你的项目中去。设置 Ray.png 做为你imageview的image, 而后把 image view的模式改成Aspect Fit而且设置它的背景颜色为白色。接着把label的text写为“ray”。

你的布局如今看上去应该是这样的了:
Gallery with Ray

请注意如今Interface Builder 已经在label上设置一个 Height constraint了。这发生在你为你的image view设置image的时候。

Label fixed height

Interface Builder已经尝试在避免某种含糊的布局的状况发生。若是image view或者label都没有一个固定高度的话,那么Auto Layout是不知道如何从新设定他们的高度的当绿色view变化时。(对于如今而言Interface Builder彷佛会忽略设置在绿色view上面的固定Height constraint)。

让咱们来假设在某种状况下你app里的绿色view变高了100 points。那么如今这多出来的100 points在imageview和label当中是如何分配的呢?是否是imageview也变高了100 points而label保持原样呢?或者说是label变高了而imageview保持原样?或者说他们是对半分的,25/75分,46开?,或者其余某种分法?

Auto Layout是不会作这些假设的,全部只有Interface Builder来经过给定label一个固定尺寸“帮助”咱们解决这问题。固然它也能够给imageview一个固定尺寸,可是给label是更有意义的。

对于此刻来讲, 让咱们姑且先使用label上面的Height constraint。

提示: 对小布局设计来讲一个比较恰当的解决方法是改变label的“Content Compression Resistance Priority”。这点你之后会学到。若是你等不及了想使用的话,那么请直接到label的Size inspector for the label而后设置vertical Content Compression Resistance Priority到751。能够到看到label上的 Height constraint会消失掉的。

 

加入其余头像

把绿色view移动到main view的左上角,是否还记得绿色view的Horizontal Space 以及 Vertical Space constraints 断定了它在superview中的位置。依然仍是那些constraints,可是他们如今的值被设为了0 - 蓝色线条的就是他们(有白色边界的) 在window的左上角:

View in top-left corner
虽然这个view是彻底在角落里的,但它仍是须要constraints来把它定位在那里。就把他们想象成边缘值为0吧。

选中绿色view而后按 Cmd-D 复制。把复制品移到右上角去:

Green view in top-right corner

再分别复制他们把他们移动左下角以及右下角。

把屏幕设计成以下所示:

Gallery design

这几位是比较帅的程序员 :-)

运行程序,能够看到肖像方向,界面看上去还不错,可是在景观方向就不尽如人意了:

Gallery looks bad in landscape

这应该很明显能够看出错在哪里了: 你已经对4个view容器设置了固定的宽和高,因此他们会一直保持这那些尺寸,不管它的superview的尺寸如何变化。

选中4个view里面的 Width (160) and Height (230) constraints 而后删除他们。如今运行程序试试,你会获得下图所示,仍是不尽如人意:

Still looks bad in landscape

这个问题看上去有点像咱们以前在介绍里面解决过的问题,因此让咱们回想一下当时是如何解决的,你应该记得咱们是给view设置相同的宽和高来解决的。

选中全部4个view而后作 PinWidths Equally操做。再次从新选中而后再作PinHeights Equally操做。

再次运行程序而且把之转到景观方向。嗯….它仍是和以前的同样嘛。这是为何呢?

好吧,若是你仔细观察上面的截图,你会发现其实每一个view确实都有相同的高度,而且他们的宽度彷佛也相同(只不过绿色的和棕色被黄色和蓝色部分遮盖住了),因此咱们的contraints是对的,是的被知足的。如今的问题仅仅是宽度和高度不是你想要的。若是这是这样,那么确定还有其余constraints在其中起做用了。

100%确定,若是你仔细看这些view的constraints,你会看到他们一样的有Horizontal 以及 Vertical Space constraints来强迫他们定位本身的位置。 (请看main view的constraints,而不是4个子view的):

Bad H-space

更加悲剧的是,你都不能删除这些 constraint,main view的T型状对象不是蓝色粗体,因此能够推断出 Interface Builder 把他们放在那里是为了不某种布局问题的。

它为何要这么作呢? 目前只能这么解释,全部的4个view都必须拥有相同的尺寸大小是不足以决定他们确切的的尺寸应该是多少的,由于Auto Layout是不知道他们几个是如何链接在一块儿的。在咱们设计上,他们是边和边的链接在一块儿,可是他们以前却没有这种constraints。因此Auto Layout不会知道它须要把“Ray” and “Matthijs” 块宽度上须要分开。

若是Auto Layout不能经过自身才推断出这层意思的话,那你就只能本身来告诉他了。

To be related

选中 Ray 和 Matthijs 块而后选择 PinHorizontal Spacing操做。由于这些块是边与边相连的,因此在他们之间须要添加一个尺寸为0的Horizontal Space constraint,有了这个, Auto Layout 就知道他们是如何关系的了。

重要提示: Interface Builder不会自动帮你删除黄色view和superview之间的主导Horizontal Space限制(就是上一张截图所示的),但它会将它升级为一个user constraint(比较粗的T状对象)。 你如今能够把它删了。若是你不删的话,你会获得一个“Unable to simultaneously satisfy constraints”的错误当你把应用转至景观方向时。

运行程序,看看如今是什么效果了:

Landscape a bit better

这个看上稍微好一点了。如今四个view是相同宽度,但高度仍是不对的。解决方案和以前的相似:在Ray和Dennis Ritchie之间放一个 Vertical Space而后把Dennis的view和window顶部之间的Vertical Space删除。

再次运行程序,如今看上去应该是这样了:

Gallery landscape OK

请注意“Dennis Ritchie” label并不在它imageview的下方正中心。这件事最开始发生在当我想要在label里输入文字的时候。这个label初始化时是放在view的中间的,但Interface Builder仍是以为把这个中心constraint替代为一个Horizontal Space效果会更好。若是你也有这个问题,那么请选中这个label而后进行AlignHorizontal Center in Container操做来修复它。

请再次注意下这些imageview:他们是延伸出来的,由于你没有给他们设置一个固定尺寸。你可能还不知道这一点,但设置他们确实是你的义务。:) 在景观方向下,这些view是不会自动修复的。可是,若是你想要一个imageview保持它原来的比例的话,那你就不是那么走运了。若是你不使用Interface Builder来作一点修改的话,你是不可能获得下图的效果的:

Aspect ratio on images

不幸的是, Interface Builder目前不提供一些能保持view原始比例的constraints。要作那个效果,你须要经过代码本身建立以及设置constraints。在iOS 6 by Tutorials里面有一章”Intermediate Auto Layout”是介绍具体怎么作的。

小贴士:你以前可能已经知道了你能够经过在Simulated Metrics来设置方向以便于你预览用户界面。你也能够直接Interface Builder里面测试各类view的缩放行为。

选中main view,在Simulated Metrics下,把尺寸设置为Freedom。如今你能nib文件添加缩放处理,你能够把它设置成你想要的任何型状。顺便也请放心,Auto Layout会立刻从新为你计算出新的布局的:

Freeform

而后,你也要对此警戒。由于有时候当你从新设置尺寸时 Interface Builder 会给它本身添加新的constraints。就像如今这儿的右下角有一个新的Horizontal Space同样。固然这也可能会删除现有的constraints,当你把nib文件放大出它原来的bounds的时候。

接下来去哪?

若是你从头看到这里了,那么恭喜!- 你如今已经知道了关于Auto Layout的全部事情,而且已经对基础知识作了实践!可是在这方面仍是有许多须要你去学习…

如今这份教程也就是你刚读的只是 iOS 6 by Tutorials 这本书里 Beginning Auto Layout chapter章节的前半部分。后半部分会教到如何使用 Auto Layout来建立更多 “现实世界”的屏幕布局,以及有关同时使用Auto Layout 和Interface Builder 的全部技巧。

和其余视觉设计工具同样, Interface Builder 有它本身的限制可是有时候若是它和 NSLayoutConstraint对象一块儿使用的话是会效果更好。 iOS 6教程书对于这个主题投入了一整个的章节- Intermediate Auto Layout.。因此若是你想要对此刨根问底的话, 那就买书看吧

相关文章
相关标签/搜索