Xamarin Designer for iOS 中的自动布局

警告

iOS Designer 在 Visual Studio 2019 版本 16.8 和 Visual Studio 2019 for Mac 版本 8.8 中已经弃用,并且已从 Visual Studio 2019 版本 16.9 和 Visual Studio for Mac 版本 8.9 中移除。 要生成 iOS 用户界面,建议直接在运行 Xcode 的 Mac 上操作。 有关详细信息,请参阅用 Xcode 设计用户界面

自动布局(也称为“自适应布局”)是一种响应式设计方法。 与每个元素位置都硬编码到屏幕上的某个点的过渡布局系统不同,自动布局与关系有关 - 元素位置相对于设计图面上的其他元素。 自动布局的核心是约束或规则的概念,这些约束或规则定义一个元素或一组元素在屏幕上其他元素的上下文中的放置。 由于元素不依赖于屏幕上的特定位置,因此约束有助于创建在不同屏幕大小和设备方向上看起来合理的自适应布局。

本指南介绍约束以及如何在 Xamarin iOS 设计器中使用这些约束。 本指南不介绍如何以编程方式使用约束。 有关以编程方式使用自动布局的信息,请参阅 Apple 文档

要求

Xamarin Designer for iOS 在 Visual Studio for Mac 和 Windows 上的 Visual Studio 2017 及更高版本中可用。

本指南假定你从 iOS 设计器简介指南中了解了设计器的组件。

约束简介

约束是屏幕上两个元素之间关系的数学表示形式。 将 UI 元素的位置表示为数学关系可以解决与 UI 元素位置硬编码相关的几个问题。 例如,如果要将屏幕底部的按钮 20px 以纵向模式放置,按钮的位置将处于横向模式时的屏幕之外。 为避免这种情况,我们可以设置一个约束,将放置视图底部的按钮 20px 的下边缘。 然后,按钮边缘的位置将计算为 button.bottom = view.bottom - 20px,这将以纵向和横向模式放置视图底部的按钮 20px。 基于数学关系计算放置位置的功能使约束在 UI 设计中非常有用。

设置约束时,我们将创建一个 NSLayoutConstraint 对象,它将用作要约束的对象的参数以及将对其执行约束的属性或特性。 在 iOS 设计器中,特性包括元素的等边缘。 还包括大小特性,如高度宽度,以及中心点位置 centerXcenterY。 例如,当我们在两个按钮的左边界位置上添加约束时,设计器将在封面下生成以下代码:

View.AddConstraint (NSLayoutConstraint.Create (Button1, NSLayoutAttribute.Left, NSLayoutRelation.Equal, Button2, NSLayoutAttribute.Left, 1, 10));

下一部分介绍如何使用 iOS 设计器处理约束,包括启用和禁用自动布局和使用约束工具栏。

启用自动布局

默认 iOS 设计器配置已启用约束模式。 但是,如果需要手动启用或禁用它,可以执行两个步骤:

  1. 单击设计图面的空白区域。 这会取消选择任何元素,并显示“情节提要”文档的属性。

  2. 选中或取消选中属性面板中的“使用自动布局”复选框:

    The Use Autolayout checkbox in the property panel

默认情况下,不会在图面上创建或显示任何约束。 相反,它们会在编译时从框架信息中自动推断。 若要添加约束,我们需要在设计图面上选择一个元素并向其添加约束。 可以使用约束工具栏执行此操作。

约束工具栏

The Context Menu Commands

约束工具栏已更新,现在由两个主要部分组成:

  • 约束模式按钮开关:以前,可以通过再次单击设计图面上的所选视图进入约束模式。 现在,应使用约束栏中的此切换按钮:

    contraints modes toggle

  • “更新约束”按钮:请务必注意,更改取决于你是否处于约束编辑模式。

    • 在约束编辑模式下,此按钮调整约束以匹配元素框架。
    • 在框架编辑模式下,此按钮调整元素框架以匹配约束所定义的位置。

约束编辑弹出框

借助约束编辑器弹出框,我们可以为选择视图一次性添加和更新多个约束。 我们可以创建多个间距、纵横比和对齐约束,例如将视图与两个视图的左边缘对齐。

若要在所选视图上编辑约束,请单击省略号显示弹出框:constraints editing popover

打开约束弹出框后,它会在视图上显示任何预设约束。 我们可以从右上角的组合框中选择“所有边”来设置所有间距约束,然后选择“全部清除”来移除。

W 将设置宽度,H 将设置高度约束。 勾选纵横比时,视图高度和宽度将控制在不同的屏幕大小,视图的宽度用作配给的分子,高度用作分母。

constraints spacing

间距约束的四个组合框列出了用于定位约束的相邻视图

基于图面的约束编辑

为了进行更精细的约束编辑,我们可以直接在设计图面上与约束交互。 本部分介绍基于图面的约束编辑相关基础知识,包括固定间距控件、放置区域以及处理不同类型的约束。

创建约束

iOS 设计器工具提供两种类型的控件用于在设计图面上操作元素。 拖放控件固定间距控件,如下图所示:

view controls

通过在约束栏中选择约束模式按钮来切换。

元素每一侧的 4 个 T 形图柄定义约束元素的边缘。 元素右侧和底部的两个 I 形图柄分别定义高度宽度约束。 中间的方形图柄定义 centerXcenterY 约束。

若要创建约束,请选择一个句柄并将其拖动到设计图面上的某个位置。 开始拖动时,图面上将显示一系列绿色线条/框,告诉你可以约束什么。 例如,在下面的屏幕截图中,我们将约束中间按钮的顶部:

Constraining the top side of the middle button

请注意其他两个按钮上的三条绿色虚线。 绿线指示放置区域或者我们可以约束到的其他元素的特性。 在上面的屏幕截图中,其他两个按钮提供 3 个垂直放置区域(centerY)来约束按钮。 视图顶部的绿色虚线表示视图控制器在视图顶部提供约束,而实心绿框表示视图控制器在顶部布局参考线下方提供约束。

重要

布局参考线是特殊类型的约束目标,可用于创建考虑到系统栏(如状态栏或工具栏)的顶部和底部约束。 主要用途之一是使应用在 iOS 6 和 iOS 7 之间兼容,因为最新版本的容器视图在状态栏下方扩展。 有关顶部布局参考线的详细信息,请参阅 Apple 文档

接下来的三个部分介绍了如何使用不同类型的约束。

大小约束

使用大小约束 - 高度宽度 - 有两个选项。 第一个选项是拖动图柄来约束相邻元素大小,如上面的示例所示。 另一个选项是双击图柄来创建自约束。 这样,我们就可以指定常量大小值,如以下屏幕截图所示:

Drag the handle to constrain to a neighbor element size, as illustrated here

中心约束

方形图柄将创建 centerXcenterY 约束,具体取决于上下文。 拖动方形图柄可点亮其他元素以提供垂直和水平放置区域,如以下屏幕截图所示:

Center Constraints

如果选择垂直放置区域,将创建 centerY 约束。 如果选择水平放置区域,约束将基于 centerX

组合约束

若要在两个元素之间创建对齐和大小相等约束,可以从顶部工具栏中选择项以按顺序指定水平对齐、垂直对齐和大小相等性,如以下屏幕截图所示:

Combinational Constraints

可视化和编辑约束

添加约束时,如果选择项,该约束将在设计图面上显示为一条蓝线:

Visualizing Constraints

可以通过单击蓝线并直接在属性面板中编辑约束值来选择约束。 或者,双击蓝线将显示一个弹出框,用于直接在设计图面上编辑值:

Editing Constraints

约束问题

使用约束时,可能会出现多种问题:

  • 冲突约束 — 当多个约束强制元素的某个特性拥有冲突值并且约束引擎无法协调这些约束时,就会发生这种情况。
  • 欠约束的项 — 元素的属性(位置 + 大小)必须完全由其约束集和内部大小覆盖,才能使约束有效。 如果这些值不明确,则表示该项欠约束。
  • 框架错放 — 当元素的框架及其约束集定义产生的两个不同矩形时,会出现这种情况。

本部分详细说明了上面列出的三个问题,并详细介绍了如何处理这些问题。

冲突约束

冲突约束用红色标记,并带有警告符号。 将鼠标悬停在警告符号上会显示一个弹出窗口,其中包含有关冲突的信息:

Conflicting Constraints warning

欠约束的项

欠约束的项以橙色显示,并触发视图控制器对象栏中橙色标记图标的外观:

Underconstrained items appear in orange

如果单击该标记图标,可以获取有关场景中欠约束的项的信息,并通过完全约束它们或移除其约束来解决问题,如以下屏幕截图所示:

Fixing Underconstrained Items

框架错放

框架错放使用与欠约束的项相同的颜色代码。 该项将始终使用其本机框架呈现在图面上,但在框架错放的情况下,红色矩形将标记项在应用程序运行时最终会出现的位置,如以下屏幕截图所示:

Sample Frame Misplacement view

若要解决框架错放错误,请从约束工具栏中选择“基于约束更新框架”按钮(最右侧的按钮):

Update Frames based on Constraints toolbar button

这会自动调整元素框架以匹配控件定义的位置。

修改代码中的约束

根据应用的要求,有时可能需要在代码中修改约束。 例如,若要调整或重新定位约束附加到的视图,请更改约束的优先级或完全停用约束。

若要在代码中访问约束,首先必须通过执行以下操作在 iOS 设计器中公开它:

  1. 按正常方式创建约束(使用上面列出的任意方法)。

  2. 在“文档大纲资源管理器”中,找到所需的约束并选择它:

    The Document Outline Explorer

  3. 接下来,在“属性资源管理器”的“小组件”选项卡中为约束分配“名称”:

    The Widget Tab

  4. 保存所做更改。

完成上述更改后,可以在代码中访问约束并修改其属性。 例如,可以使用以下命令将附加视图的高度设置为零:

ViewInfoHeight.Constant = 0;

如果给定 iOS 设计器中为约束进行了以下设置:

Editing a Constraint in the Property Explorer

延迟布局传递

自动布局引擎不会立即更新附加视图来响应约束,而是为近期计划延迟布局传递。 在此延迟传递期间,不仅给定视图的约束已更新,层次结构中每个视图的约束都会重新计算和更新,以调整新布局。

随时可以通过调用父视图的 SetNeedsLayoutSetNeedsUpdateConstraints 方法来计划自己的延迟布局传递。

延迟布局传递由通过视图层次结构的两个唯一传递:

  • 更新传递 - 在此传递中,自动布局引擎遍历视图层次结构,并在所有视图控制器上调用 UpdateViewConstraints,在所有视图上调用 UpdateConstraints 方法。
  • 布局传递 - 自动布局引擎再一次遍历视图层次结构,但此次在所有视图控制器上调用 ViewWillLayoutSubviews,在所有视图上调用 LayoutSubviews 方法。 LayoutSubviews 方法使用自动布局引擎计算的矩形更新每个子视图的 Frame 属性。

对约束更改进行动画处理

除了修改约束属性之外,还可以使用核心动画对视图约束的更改进行动画处理。 例如:

UIView.BeginAnimations("OpenInfo");
UIView.SetAnimationDuration(1.0f);
ViewInfoHeight.Constant = 237;
View.LayoutIfNeeded();

//Execute Animation
UIView.CommitAnimations();

此处的键在动画块内调用父视图的 LayoutIfNeeded 方法。 这会告知视图绘制已进行动画处理的位置或大小更改的每个“框架”。 如果没有此行,视图将直接对齐到最终版本,无动画处理。

总结

本指南介绍了 iOS 自动(或“自适应”)布局和约束概念,作为设计图面上元素之间的关系的数学表示形式。 本文介绍了如何在 iOS 设计器中启用自动布局、使用约束工具栏,以及如何在设计图面上单独编辑约束。 接下来,它介绍了如何排查三个常见约束问题。 最后,它演示了如何在代码中修改约束。