iOS-Auto Layout[2]-Interface Builder

当拖一个View或者Control到画布上时,Interface Builder会自动给其建立一组与画布左上角相关的Prototyping Constraints。当创建一个Constraint后,Prototyping Constraints将被自动移除。

Auto Layout和Constraints的原理参考Auto Layout[1]-Constraints

Interface Builder提供了三种配置Auto Layout Constraints的方式,分别是Control-Dragging、Pin & Align Tools和通过Interface Builder自动建立Constraints后进行编辑三种方式。

Control-Dragging

按住Control键,并按住某个View并拖动到另一个View上:

Auto Layout-ControlDragging-Begin

出现一个选择项:

Auto Layout-ControlDragging-Option

如果拖动的方向偏水平,则会出现水平的Constraints选项,反之,则会出现垂直的。

尽管Control-Dragging的方式很快,但是其是基于当前的Scene的Layout进行的,如果需要更精细的控制,使用下述的方法。

Stack,Align,Pin and Resolve Tools

Interface Builder在右下角提供了四类工具:

Auto Layout-Tools

Stack Tool

选择一个View,并点击Stack Tool,会自动创建一个StackView,并将其原先的View嵌入到StackView中。

Align Tool

Align Tool一般用于快速地排列一组元素,选择多个需要水平或者垂直排列的View,并点击Align Tool,会弹出一个选择项:

Auto Layout-Align Tool

在Leading Edges输入100,则第二个到最后一个View都会以第一个View的Leading为基准,向右偏移100,即除了第一个View,其他View.x的位置都比第一个View.x大100。

Pin Tool

Pin Tool一般用于快速地定义一个View相对于旁边View的位置,或者快速地定义大小。选择一个View,并点击Pin Tool,会弹出一个选择项:

Auto Layout-Pin Tool

在Top Edges输入100,则将其位置调整到离它上面最近的View距离100的位置,点击下拉框,可以选择其他View为标准,不一定是最近的。

Auto Layout-Pin Tool-Top

Resolve Auto Layout Issues Tool

Resolve Auto Layout Issues Tool提供了一些对整体Views操作的选项,上方是对选中的Views进行操作,下方是对所有Views进行操作。

Auto Layout-Resolve Auto Layout Issues Tool

使用IB自动创建Constraints

IB可以自动创建Constraints,首先在画布上布局好Views的大小和位置,并选择需要自动创建Constraints的Views,然后点击:

Resolve Auto Layout Issues tool > Reset to Suggested Constraints

IB会自动创建这些Views在当前布局中的Constraints。

也可以预先在Views上添加了Constraints,然后点击:

Resolve Auto Layout Issues tool > Add Missing Constraints

IB会自动补齐Constraints。

查找和编辑Constraints

Constraints in Canvas

I-bars

显示两个Item之间空间的大小,或者Item的高宽度。

AutoLayout-IBars

Plain Lines

显示View的Edges。

AutoLayout-PlainLines

Solid Lines

表示Priority=1000。

AutoLayout-BlueLines

Dashed Lines

表示Priority<1000。

AutoLayout-DashedLines

Red Lines

表示有错误,可能是Constraint存在歧义,或者无解。

AutoLayout-RedLines

Orange Lines

表示View当前的位置与Constraint不符,可能是刚被拖动导致。

AutoLayout-OrangeLines

Blue Lines

表示Constraint没有问题。

AutoLayout-BlueLines

Equal Badges

表示长度或宽度相等。

AutoLayout-EqualBadges

Greater-than-or-equal and less-than-or-equal badges

表示不等式。

AutoLayout-InequalBadges

Constraints in Doucument Outline

AutoLayout-Document Outline

Constraints in Inspector

Size Inspector中可以看到选中View的Constraints。

AutoLayout-Inspector

Examing & Editing

当点击一个Constraints进行编辑时,可以看到Inspector:

AutoLayout-Margin-Edit

其中的identifier是用于Constraint在控制台或者其他Debug任务的识别名称,Placeholder表示该Constraint只在设计阶段存在,在运行时会被移除。

Size Class-Based Layouts

IB下方有一个图标,如下:

AutoLayout-ClassBased

可以用于选择不同尺寸,用于适配不同屏幕,例如,可以直接在IB中通过选择不同的矩形,查看横屏和竖屏的布局。

需要注意的点:

  • 从Canvas或者Document Outline中删除某个项,将会直接从项目中移除,包括所有的Size Class;
  • 从其他地方删除某个项,只会从当前Size Class中移除;
  • Command-Deleting某个项,只会从当前Size Class中移除;
  • 如果选择的是Any-Any模式,删除某个项将会直接从项目中移除。

Features

iOS系统上有一些与Auto Layout交互的Features(特性)。

Top & Bottom Layout Guides

Top & Bottom Layout Guides表示当前View Controller的可见内容区域的上下边界,不包含Bars(Status Bar、Navigation Bar、Tab Bar)。

Layout Guides适配了UILayoutSupport协议,提供length属性,该属性表示ViewController的View的边界与Guide的边界之间的距离,例如,上方的就是View的Top与Bars的Bottom之间的距离。

Layout Margins

Auto Layout默认给每个View定义好了Margins(内间距),便是View与SubViews的边缘的距离,通过layoutMargins或者layoutMarginsGuide属性可以设置。

Margins的默认值为8,而ViewController的Root View的Margins是由系统维护的,上下Margins为0,而左右Margins取决于Controllers呈现的方式,只能是16或者20,无法修改。

当放置一个View到它的SuperView中时,一般使用Layout Margins而不是Edges,NSLayoutAttribute中定义了所有的Margins属性。

IB中,当使用Control-Dragging方式时,默认使用Margins来创建Constraints,如下图:

AutoLayout-Margin-ControlDrag

当使用Pin Tool方式时,可以勾选”Constrain to margins”的选项框,如果没被勾选,则使用Edges,如下图:

AutoLayout-Margin-PinTool

当点击一个Constraints进行编辑时,可以看到在First Item和Second Item中可以选择“Relative to Margin”,如果不选择,则是Edges,如下图:

AutoLayout-Margin-Edit

当在代码中创建与SuperView的Margins相关的Constraints时,使用layoutMarginsGuide属性。

Readable Content Guides

View的Readable Content Guides属性表示该View中文本对象的可选最大长度,理想状态下,文本足够短以便用户可以直接阅读他,而不需要转动脑袋。

Readable Content Guides一般是在View的Layout Margins中且居中,其Size随着系统的动态Size变化而变化。当用户选择更大的字体时,系统创建更宽的Guides以便阅读。

在IB中,你可以设置Views的Margins表示Layout Margins还是Readable Content Guides,选择一个View,在Size Inspector中可以勾选”Follow Readable Width”进行选择。

AutoLayout-Margin-ReadableContentGuide

Semantic Content

如果设置了Leading & Trailing Constraints,则当转换语言方向时(有些国家习惯从右到左),此时Views会自动被翻转,然而,一些Views由于特殊的原因,是不能被翻转的,例如游戏里面控制上下左右的旋杆。

semanticContentAttribute属性可以设置View是否会被翻转,在IB中,View Insepctor中可以设置该属性,如下图:

AutoLayout-Semantic

默认是Unsecified,此时View会随着阅读方向的变化而翻转,如果设置成Spatial,Playback,Force Left-to-Right,则一直从左到有,设置成Force Right-to-Left,则一直从右到左。

Rules of Thumb

下面是一些注意点和使用技巧:

  • 不用使用Frame,Bounds和Center属性来声明View的几何信息;
  • 尽可能使用Stack View,Stack View可以自动管理内容的Layout;
  • 在两个相邻的Views之间创建Constraints,而不要越过其中一个去连其他较远的View;
  • 避免给Views赋值固定的宽高度,可以通过设置Size最大最小区间;
  • 尝试使用Pin & Align Tools,常常可以解决一些麻烦问题;
  • 小心使用自动更新Frame,如果Constraints没有定义好大小和位置,Frame经常数值为0,然后被放置到左上角;
  • 确保所有Views有着有意义的名称,以便更容易地被识别;
  • 使用Leading & Trailing替代Left & Right,原因参考Auto Layout[1]-Constraints;
  • 当在代码中初始化Views时,注意设置translatesAutoresizingMaskIntoConstraints属性为NO,否则,系统会自动根据Frame和AutoResizing Mask创建一组Constraints,很可能与你自己创建的Constraints冲突;

特别注意,如果Item与View Controller的Root View的边之间要创建Constraints时:

  • 如果是水平方向:(1)对于大多数Controls,使用跟Layout Margins的Zero-Point Constraint;(2)对于MarginToMargin填充满RootView的Text Object,使用Readable Content Guides;(3)对于EdgeToEdge填充满RootView的其他Item,使用Leading & Trailing Edges;
  • 如果是垂直方向:(1)如果View延伸到Bars下面,使用Top & Bottom Margins,特别是ScrollView,允许在Bars下滑动内容;(2)如果没有延伸到Bars下面,使用Top & Bottom Layout Guides。