iOS 从零开始使用 Swift:自动布局基础

iOS 从零开始使用 Swift系列:
探索 iOS SDK
探索 Foundation 框架
使用 UIKit 的第一步
自动布局基础
表格视图基础
导航控制器和视图控制器层次结构
iOS 上的数据持久性和沙盒
构建购物清单应用程序 1
构建购物清单应用程序 2
下一步该去哪里

在上一篇文章中,我们创建了一个简单的应用程序,只有一个标签和一个按钮。尽管它很简单,但该应用程序有一些布局问题。在本教程中,您将学习如何使用 Apple 的布局系统 Auto Layout 来解决这些问题。让我们从一个新项目开始。

介绍

打开 Xcode 并创建一个新项目,选择 Single View Application模板。将您的应用程序命名 为Auto Layout并将 Devices设置为 Universal。告诉 Xcode 将项目保存在哪里,然后单击 Create

请记住,在本系列前面的文章中,通用应用程序可以在 iPad 和 iPhone(以及 iPod Touch)上运行。这意味着用户界面需要适应运行它的设备。让我们探索它是如何工作的,以及我们需要解决哪些问题来实现它。

在项目中,打开 Main.storyboard并向视图控制器的视图添加五个标签。正如您在下面的屏幕截图中看到的那样,我将一个标签放置在视图的中心,并将一个标签放置在其每个角落。

您可能已经注意到 Xcode 试图帮助您定位标签,当您接近视图的边缘或中心时,会显示蓝色虚线指南。坚持 Xcode 的建议,让标签卡在视图边缘和中心的位置。

因为我们正在创建一个通用应用程序,所以该应用程序在 iPad 和 iPhone 上都应该看起来不错。在模拟器中运行应用程序并选择 iPad Retina(或任何其他 iPad 模拟器)作为目标。

哎哟。iPad 上的用户界面看起来不太好。只有左上角的标签位置正确。

将目标更改为 iPhone 6(或任何其他 iPhone 模拟器)并再次运行该应用程序。

iPhone 上的用户界面看起来更糟。iPhone 上甚至看不到两个标签。与 iPad 一样,只有左上角的标签位置正确。

本教程的目标是使用自动布局解决这些用户界面问题。在我们可以应用 Auto Layout 之前,我们需要知道它是什么以及它如何帮助我们。

什么是自动布局?

几年前,随着 iOS 5 的发布,iOS 上引入了自动布局。自动布局是一个描述性的布局系统,建立在约束之上。这仅仅意味着您告诉布局引擎您希望如何布局用户界面。换句话说,不是告诉布局引擎按钮需要定位在特定位置,而是描述它应该定位的位置。

约束用于定义或描述布局。例如,您告诉布局引擎一个按钮需要在其包含的视图中水平居中。布局引擎采用一组约束,将它们转换为方程式,并在用户界面中设置元素的框架。为了使这项工作,您应该添加尽可能多的约束以避免元素位置的任何歧义。

自动布局的优点很简单。由于自动布局的描述性,布局引擎会更新用户界面,而不管应用程序运行的设备的尺寸或方向如何。它还使您的应用程序永不过时。当 Apple 推出具有新屏幕尺寸的设备时,您的应用程序将自动调整其用户界面以适应新的屏幕尺寸。如果您对应用程序的用户界面进行硬编码,则情况并非如此。

现在您已经了解了 Auto Layout 是什么以及它是如何工作的,是时候探索我们如何应用 Auto Layout 来解决项目中的布局问题了。

添加约束

您还记得在将标签添加到视图控制器的视图时看到的蓝色指南吗?这些不是您要寻找的限制。就像我说的,它们是帮助您定位用户界面元素的指南。它们只不过是 Xcode 提示您遵守 Apple 的Human Interface Guidelines的提示。

有多种方法可以向用户界面元素添加约束。一种方法是使用Interface Builder底部的Pin菜单。选择左上角的标签,然后单击底部的Pin菜单。

左上角的标签还没有任何约束。让我们通过将标签固定到其父视图或父视图的左上角来改变它。使用Pin菜单,我们可以同时添加多个约束。我们还添加约束,通过选中标记为Width和 Height的复选框将标签的宽度和高度设置为固定。这就是Pin菜单的外观。请注意,未选中“ 限制到边距”复选框。

Pin菜单的底部,按钮的文本现在显示为Add 4 Constraints。Xcode 告诉我们,我们还没有添加任何约束。单击按钮添加我们在Pin菜单中指定的约束。标签的位置现在由四个约束来定义或描述。这在情节提要中通过标签周围的四条蓝线进行可视化。

在继续之前,将约束添加到右上角、左下角和右下角标签。将每个标签固定到其父视图的最近边缘非常重要。例如,右下角的标签需要固定到视图控制器视图的底部边缘和右侧边缘。这就是 右下角标签的Pin菜单的外观。

约束到位后,在模拟器中运行应用程序。这是您应该在 iPhone 6 模拟器中看到的内容。这样看起来好多了。中心标签还没有任何约束。现在让我们添加一些。

使用底部的Pin菜单选择中心标签并添加两个约束以固定标签的宽度和高度。您是否期望看到两条蓝线?如果您已正确添加约束,您应该会看到红线,而不是蓝线。这是为什么?红线表示有问题。Xcode 告诉我们标签没有足够的约束来避免歧义。标签位置的描述目前不完整。

我们已经告诉 Xcode 标签应该有一个固定的宽度和一个固定的高度。我们还没有定义标签的水平和垂直位置。您可以通过检查左侧面板中的错误来了解有关该问题的更多信息。您应该在View Controller Scene的左侧看到一个红色箭头。单击箭头以阅读错误消息。

错误告诉我们 X 和 Y 位置未定义。如果您单击错误旁边的红色圆圈,Xcode 会为您提供通过添加缺少的约束来修复问题的选项。让我们不要偷懒,自己解决问题。

为了使标签居中,无论应用程序运行的设备的尺寸和方向如何,我们都不能使用 Pin菜单。相反,我们使用 Pin 菜单左侧的Align菜单。选择标签后,打开 对齐菜单并添加两个约束以使标签在其父视图中居中。通过添加这些约束,红线被蓝线取代。

检查约束

是时候了解有关约束的更多信息了。约束不是静态的,它们当然不是神奇的。您可以添加、删除和修改约束。作为一个例子,让我们看一下中心标签的约束。选择标签并打开 左侧的尺寸检查器。约束部分列出了对当前选择的约束,即中心标签。每个约束都有一个 编辑按钮来修改约束的属性。

单击 显示为Width Equals: 42的约束的Edit按钮。通过修改 Constant属性,您可以更改标签的宽度。将 Constant设置为 100,然后按 Enter或 Return以提交更改。故事板中标签的大小立即反映了我们所做的更改。

如果多个约束相互冲突,则约束的优先级属性很重要。让我们用一个例子来说明这一点。选择中心标签并添加一个将标签宽度设置为200的新约束。你已经知道如何做到这一点。添加新约束时,Xcode 抱怨它不能同时满足两个约束。

选择标签并打开 Size Inspector以检查约束。有两个约束设置标签的宽度。单击 Width Equals: 100约束 的Edit 按钮并将 Priority设置为 High (750)。情节提要中标签的宽度变为200  ,其中一条蓝线从实线变为虚线,表明此约束已被具有更高优先级的约束所推翻。虚线约束仍处于活动状态,但由于与将标签宽度设置为200的约束相比,它的优先级较低,因此当前未应用。

还有另一种解决问题的方法。将两个约束的优先级设置为 Required (1000)。同时将= 改为 >= 对于读取Width Equals: 100的约束。这也解决了这个问题。不过结果不一样。这两个约束都有效,共同定义标签的位置。约束现在定义标签的宽度应大于或等于100

添加更多约束

我已经提到有几种方法可以在界面生成器中添加约束。让我们看看另一种流行的技术。打开 右侧的Object Library并在视图控制器的视图中添加一个文本字段。要将文本字段固定到视图顶部,请选择文本字段,按 Control并从文本字段拖动到视图顶部。请看下面的屏幕截图以进行澄清。

从弹出的菜单中,选择 Vertical Spacing to Top Layout Guide。顶部布局指南是位于状态栏和导航栏底部边缘的特殊指南。顶部布局指南的位置取决于顶部是否存在状态栏和导航栏。

文本字段现在应该固定在视图的顶部。正如预期的那样,Xcode 告诉我们文本字段没有足够的约束来明确地描述它的位置。

选择文本字段,按 Control并拖动到文本字段左侧的标签。从菜单中,选择 水平间距。对文本字段右侧的标签重复此步骤。我们快到了。

要将标签的高度设置为固定,请选择文本字段,按Control并从文本字段的顶部拖动到文本字段的底部。从出现的菜单中选择 高度。这定义了关于文本字段本身的约束,即它的高度。

我相信您同意自动布局的基础知识很容易理解。不过,它有时会变得相当复杂。到目前为止,我们介绍的是基础知识,Auto Layout 展示了它的力量。让我们通过查看一个非常常见的问题来完成本教程,该问题很容易通过 Auto Layout 解决。

更多约束

您希望子视图跨越其父视图的宽度和高度的情况并不少见。例如,表格视图通常与其父视图大小相同。让我们看看我们如何使用自动布局来处理这个问题。

将对象库中的视图添加 到视图控制器的视图中。打开 Attributes Inspector并将视图的背景设置为蓝色以确保它突出。在 iPad 模拟器中运行应用程序,看看我们从什么开始。

您可以按 Command + 左箭头 或 Command + 右箭头来旋转设备。看起来视图保持其宽度和高度,但它被粘在左上角。目标是让它跨越其父视图的宽度和高度。选择蓝色视图并使用Pin菜单添加以下约束 。

在单击 Add 4 Constraints之前,请确保添加与蓝色视图的超级视图相关的约束。这意味着什么?约束描述了两个视图之间的关系。您即将将这些约束应用于与其最近的兄弟相关的蓝色视图。然而,我们想要的是添加约束来定义蓝色视图相对于其包含视图或父视图的位置。您可以通过单击数字旁边的小三角形(定义约束的常数)来指定约束定义的视图。请查看以下屏幕截图以进行说明。

指定约束视图

仔细检查每个约束是否适用于蓝色视图及其父视图或包含视图。准备好后,添加四个约束。

您可能看到的不是蓝色线条,而是带有数字的橙色线条。在 Xcode 中,橙色表示警告。橙色线警告您蓝色视图的当前位置与运行时蓝色视图的位置不一致。你注意到蓝色视图的父视图边缘的橙色虚线了吗?如果您刚刚应用的约束有效,那么这些虚线表示蓝色视图的框架。这发生在运行时。

如果您不相信我,我建议您在 iPad 模拟器中运行该应用程序,自己看看。蓝色视图跨越其父视图的宽度和高度,即使您将模拟器从纵向旋转到横向,反之亦然。

橙色线不必要地使工作区混乱,并且您看到的不是您在运行时得到的。最好通过更新蓝色视图的框架来解决此问题。这很简单。选择蓝色视图并 从 右下角的Resolve Auto Layout Issues菜单中选择Update Frames 。

确保您了解我们在本教程中介绍的内容,因为我们将在本系列的其余部分中需要它。在下一个教程中,我们将讨论表格视图,并且我们将应用本教程中讨论的一些技术。要了解有关自动布局的更多信息,请浏览 Apple 的自动布局指南

结论

说自动布局功能强大是轻描淡写的。尽管我们在本教程中只触及了皮毛,但您现在应该知道什么是自动布局以及它可以为您做什么。

ios-from-scratch-with-swift-auto-layout-basics–cms-25520