企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] 以下配方演示了如何处理具有内在内容大小的视图。 通常,内在内容大小简化了布局,减少了所需的约束数量。 但是,使用内在内容大小通常需要设置视图的内容拥抱和抗压缩(CHCR)优先级,这会增加额外的复杂性。 要查看这些配方的源代码,请参阅 [Auto Layout Cookbook](https://developer.apple.com/sample-code/xcode/downloads/Auto-Layout-Cookbook.zip) 项目。 ## 第一节 简单的标签和输入框 这个配方演示了一个简单的标签和输入框对。 在此示例中,标签的宽度基于其文本属性的大小,文本字段将展开和缩小以适合剩余空间。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Label_and_Text_Field_Pair_2x.png =451x224) 由于此配方使用视图的内在内容大小,因此只需要五个约束来唯一地指定布局。 但是,您必须确保您具有正确的CHCR优先级才能获得正确的调整大小行为。 有关内在内容大小和CHCR优先级的更多信息,请参阅 [Intrinsic Content Size](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/AnatomyofaConstraint.html#//apple_ref/doc/uid/TP40010853-CH9-SW21)。 ### 1.1 视图和约束 在 Interface Builder中,拖出一个标签和一个文本字段。 设置标签的文本和文本字段的占位符,然后设置约束,如图所示。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/simple_label_and_text_field_2x.png =421x196) 1. Name Label.Leading = Superview.LeadingMargin 2. Name Text Field.Trailing = Superview.TrailingMargin 3. Name Text Field.Leading = Name Label.Trailing + Standard 4. Name Text Field.Top = Top Layout Guide.Bottom + 20.0 5. Name label.Baseline = Name Text Field.Baseline ### 1.2 属性 要使文本字段伸展以填充可用空间,其内容拥抱必须低于标签的内容。 默认情况下, Interface Builder 应该将标签的内容设置为251,文本字段设置为250。您可以在“Size inspector”检查器中对其进行验证。 | Name | Horizontal hugging | Vertical hugging | Horizontal resistance | Vertical resistance | | --- | --- | --- | --- | --- | | Name Label | 251 | 251 | 750 | 750 | | Name Text Field | 250 | 250 | 750 | 750 | ### 1.3 讨论 请注意,此布局仅使用两个约束(4和5)来定义垂直布局,以及三个约束(1,2和3)来定义水平布局。 根据创建非歧义性,可满足布局的经验法则,我们需要每个视图有两个水平和两个垂直约束; 然而,标签和文本字段的内在内容大小提供了它们的高度和标签的宽度,消除了对三个约束的需要。 此布局还简化了文本字段始终高于标签文本的假设,并使用文本字段的高度来定义与顶部布局指南的距离。 因为标签和文本字段都用于显示文本,所以配方使用文本的基线进行对齐。 水平方向,您仍需要定义应展开哪个视图以填充可用大小。 您可以通过修改视图的 CHCR 优先级来做到这一点。 在这个例子中,Interface Builder 应该已经将名称标签的水平和垂直拥抱优先级设置为 251。因为这大于文本字段的默认值 250,所以文本字段扩展为填充任何额外的空间。 > 注意 > 如果布局可能显示在控件太小的空间中,则还需要修改压缩阻力值。 压缩阻力定义在没有足够空间时应截断哪些视图。 > 在这个例子中,修改压缩阻力作为读者的练习。 如果名称标签的文字或字体足够大; 但是,没有足够的空间,产生模糊的布局。 系统然后选择一个约束断开,并且文本字段或标签被截断。 > 理想情况下,您希望为可用空间创建一个永不过大的布局 - 根据需要使用紧凑尺寸类的替代布局。 但是,在设计支持多种语言和动态类型的视图时,很难准确预测行可能会变大。 为了以防万一,修改抗压性是一个很好的安全阀。 ## 第二节 动态高度标签和文本字段 简单标签和文本字段配方通过假定文本字段总是比名称标签更高来简化布局逻辑。 然而,这并不总是正确的。 如果您足够增加标签的字体大小,它将扩展到文本字段上方。 此配方根据运行时最高控件动态设置控件的垂直间距。 使用常规系统字体,此配方看起来与简单标签和文本字段配方相同(请参见屏幕截图)。 但是,如果将标签的字体大小增加到 36.0,则布局的垂直间距将根据标签的顶部进行计算。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Label_and_Text_Field_Pair_2x.png =451x224) 这是一个有点人为的例子。 毕竟,如果增加标签的字体大小,通常也会增加文本字段的字体大小。 但是,考虑到通过iPhone的可访问性设置提供额外的额外超大字体,这种技术在混合动态类型和固定大小的控件(如图像)时证明是有用的。 ### 2.1 视图和约束 像在简单标签和文本字段中那样设置视图层次结构,但使用更复杂的一组约束: ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/dynamic_height_label_and_text_field_2x.png =421x196) 1. Name Label.Leading = Superview.LeadingMargin 2. Name Text Field.Trailing = Superview.TrailingMargin 3. Name Text Field.Leading = Name Label.Trailing + Standard 4. Name Label.Top >= Top Layout Guide.Bottom + 20.0 5. Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249) 6. Name Text Field.Top >= Top Layout Guide.Bottom + 20.0 7. Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249) 8. Name label.Baseline = Name Text Field.Baseline ### 2.2 属性 要使文本字段伸展以填充可用空间,它的内容拥抱必须低于标签的内容。 默认情况下,Interface Builder应该将标签的内容设置为251,文本字段设置为250.您可以在“大小”检查器中对其进行验证。 | Name | Horizontal hugging | Vertical hugging | Horizontal resistance | Vertical resistance | | --- | --- | --- | --- | --- | | Name Label | 251 | 251 | 750 | 750 | | Name Text Field | 250 | 250 | 750 | 750 | ### 2.3 讨论 这个配方为每个控件使用一对约束。 一个必需的,大于或等于约束条件定义了该控件和布局指南之间的最小距离,而一个可选的约束条件试图将控件从布局指南中精确地拉到20.0点。 对于较高的约束条件,两个约束条件都可以满足,所以系统将它从布局指南中精确定位20.0个点。 但是,对于较短的控制,只有最小距离是可满足的。 另一个约束被忽略。 这使得自动布局系统可以在运行时随着控件高度的变化动态地重新计算布局。 > 注意 > 请务必将可选约束的优先级设置为低于默认内容拥抱限制(250)的值。 否则,系统会中断内容拥抱约束并拉伸视图,而不是重新定位视图。 > 在处理使用基线对齐的布局时,这可能会特别令人困惑,因为基线对齐只有在文本视图显示在内在内容高度时才有效。 如果系统调整其中一个视图的大小,则文本可能无法正确排列,尽管具有所需的基线约束。 ## 第三节 固定高度的列 此配方将简单标签和文本字段配方扩展为标签和文本字段列。 在这里,所有标签的后沿对齐。 文本字段的前端和后端对齐,水平位置基于最长的标签。 然而,与简单标签和文本字段配方一样,此配方通过假定文本字段始终高于标签来简化布局逻辑。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Label_and_Text_Field_Columns_2x.png =451x297) ### 3.1 视图和约束 布置标签和文本字段,然后如图所示设置约束。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/fixed_height_columns_2x.png =472x393) 1. First Name Label.Leading = Superview.LeadingMargin 2. Middle Name Label.Leading = Superview.LeadingMargin 3. Last Name Label.Leading = Superview.LeadingMargin 4. First Name Text Field.Leading = First Name Label.Trailing + Standard 5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard 6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard 7. First Name Text Field.Trailing = Superview.TrailingMargin 8. Middle Name Text Field.Trailing = Superview.TrailingMargin 9. Last Name Text Field.Trailing = Superview.TrailingMargin 10. First Name Label.Baseline = First Name Text Field.Baseline 11. Middle Name Label.Baseline = Middle Name Text Field.Baseline 12. Last Name Label.Baseline = Last Name Text Field.Baseline 13. First Name Text Field.Width = Middle Name Text Field.Width 14. First Name Text Field.Width = Last Name Text Field.Width 15. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0 16. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard 17. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard ### 3.2 属性 在“属性”检查器中,设置以下属性。 特别是,将所有标签中的文本对齐。 这使您可以使用比文本更长的标签,并且仍然排列文本字段旁边的边缘。 | View | Attribute | Value | | --- | --- | --- | | First Name Label | Text | First Name | | First Name Label | Alignment | Right | | First Name Text Field | Placeholder | Enter first name | | Middle Name Label | Text | Middle Name | | Middle Name Label | Alignment | Right | | Middle Name Text Field | Placeholder | Enter middle name | | Last Name Label | Text | Last Name | | Last Name Label | Alignment | Right | | Last Name Text Field | Placeholder | Enter last name | 对于每一对,标签的拥抱内容必须高于文本字段。 同样,Interface Builder 应该自动执行此操作; 不过,您可以在“大小”检查器中验证这些优先级。 | Name | Horizontal hugging | Vertical hugging | Horizontal resistance | Vertical resistance | | --- | --- | --- | --- | --- | | First Name Label | 251 | 251 | 750 | 750 | | First Name Text Field | 250 | 250 | 750 | 750 | | Middle Name Label | 251 | 251 | 750 | 750 | | Middle Name Text Field | 250 | 250 | 750 | 750 | | Last Name Label | 251 | 251 | 750 | 750 | | Last Name Text Field | 250 | 250 | 750 | 750 | ### 3.3 讨论 此配方基本上以简单标签和文本字段布局的三个副本开始,一个堆叠在另一个上面。 但是,您需要进行一些添加,以便行正确排列。 首先,通过右对齐每个标签的文本来简化问题。 现在您可以使所有标签具有相同的宽度,并且无论文本的长度如何,都可以轻松对齐它们的尾部边缘。 此外,由于标签的抗压强度大于其内容拥抱度,因此所有标签都倾向于拉伸而不是挤压。 将前缘和后缘对齐,并且标签自然延伸至最长标签的内在内容尺寸。 因此,您只需要对齐所有标签的前端和后端。 您还需要对齐所有文本字段的前缘和后缘。 幸运的是,标签的前沿已经与superview的前沿保证金一致。 类似地,文本字段的后沿都与superview的尾部边距对齐。 您只需要排列另外两个边之一,并且因为所有行都是相同的宽度,所以所有行都将对齐。 有很多方法可以做到这一点。 对于这个配方,给每个文本字段等宽。 ## 第四节 动态高度列 这个配方结合了你在动态高度标签和文本字段配方和固定高度列配方中学到的所有东西。这个配方的目标包括: * 根据最长标签的长度对齐标签的尾部边缘。 * 文本字段的宽度相同,并且它们的前缘和后缘对齐。 * 文本字段展开以填充超级视图中的所有剩余空间。 * 行之间的高度基于行中最高的元素。 * 一切都是动态的,所以如果字体大小或标签文字改变,布局会自动更新。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Label_and_Text_Field_Columns_2x.png =451x297) ### 4.1 视图和约束 像在固定高度列中一样布置标签和文本字段; 但是,您需要一些额外的限制。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/dynamic_columns_2x.png =421x393) 1. First Name Label.Leading = Superview.LeadingMargin 2. Middle Name Label.Leading = Superview.LeadingMargin 3. Last Name Label.Leading = Superview.LeadingMargin 4. First Name Text Field.Leading = First Name Label.Trailing + Standard 5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard 6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard 7. First Name Text Field.Trailing = Superview.TrailingMargin 8. Middle Name Text Field.Trailing = Superview.TrailingMargin 9. Last Name Text Field.Trailing = Superview.TrailingMargin 10. First Name Label.Baseline = First Name Text Field.Baseline 11. Middle Name Label.Baseline = Middle Name Text Field.Baseline 12. Last Name Label.Baseline = Last Name Text Field.Baseline 13. First Name Text Field.Width = Middle Name Text Field.Width 14. First Name Text Field.Width = Last Name Text Field.Width 15. First Name Label.Top >= Top Layout Guide.Bottom + 20.0 16. First Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249) 17. First Name Text Field.Top >= Top Layout Guide.Bottom + 20.0 18. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249) 19. Middle Name Label.Top >= First Name Label.Bottom + Standard 20. Middle Name Label.Top = First Name Label.Bottom + Standard (Priority 249) 21. Middle Name Text Field.Top >= First Name Text Field.Bottom + Standard 22. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard (Priority 249) 23. Last Name Label.Top >= Middle Name Label.Bottom + Standard 24. Last Name Label.Top = Middle Name Label.Bottom + Standard (Priority 249) 25. Last Name Text Field.Top >= Middle Name Text Field.Bottom + Standard 26. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard (Priority 249) ### 4.2 属性 在“属性”检查器中,设置以下属性。 特别是,将所有标签中的文本对齐。 正确对齐标签可让您使用比其文本更长的标签,并且文本的边缘仍然排列在文本字段旁边。 | View | Attribute | Value | | --- | --- | --- | | First Name Label | Text | First Name | | First Name Label | Alignment | Right | | First Name Text Field | Placeholder | Enter first name | | Middle Name Label | Text | Middle Name | | Middle Name Label | Alignment | Right | | Middle Name Text Field | Placeholder | Enter middle name | | Last Name Label | Text | Last Name | | Last Name Label | Alignment | Right | | Last Name Text Field | Placeholder | Enter last name | 对于每一对,标签的拥抱内容必须高于文本字段。 同样,Interface Builder 应该自动执行此操作; 不过,您可以在“大小”检查器中验证这些优先级。 | Name | Horizontal hugging | Vertical hugging | Horizontal resistance | Vertical resistance | | --- | --- | --- | --- | --- | | First Name Label | 251 | 251 | 750 | 750 | | First Name Text Field | 250 | 250 | 750 | 750 | | Middle Name Label | 251 | 251 | 750 | 750 | | Middle Name Text Field | 250 | 250 | 750 | 750 | | Last Name Label | 251 | 251 | 750 | 750 | | Last Name Text Field | 250 | 250 | 750 | 750 | ### 4.3 讨论 该配方简单地结合了动态高度标签和文本字段以及固定高度列配方中描述的技术。 与动态高度标签和文本字段配方类似,此配方使用成对约束来动态设置行之间的垂直间距。 与固定高度列配方类似,它使用标签中的右对齐文本和明确的等宽限制来排列列。 > 注意 > 本示例使用 20.0 点空间来填充视图和顶部布局指南之间的距离,并在同级视图之间使用8.0空间。 这具有设定固定的 20 点顶部边界的效果。 如果您需要一个可自动根据是否存在 bar 进行调整的余量,则必须添加其他约束。 通用技术显示在 [Adaptive Single View](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSimpleConstraints.html#//apple_ref/doc/uid/TP40010853-CH12-SW4) 配方中。 然而,确切的实施对读者来说是一个挑战。 正如你所看到的,布局的逻辑开始变得有些复杂; 然而,有几种方法可以简化事情。 首先,如前所述,您应尽可能使用堆栈视图。 或者,您可以对控件进行分组,然后布局组。 这使您可以将单个复杂的布局分解为更小,更易于管理的块。 ## 第五节 两个等宽按钮 这个配方展示了两个相同大小的按钮。 垂直方向上,按钮与屏幕底部对齐。 在水平方向上,它们被拉伸以便填充所有可用空间。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Two_Equal-Width_Buttons_screen_2x.png =451x224) ### 5.1 视图和约束 在 Interface Builder 中,将两个按钮拖到场景中。 使用场景底部的准则对齐它们。 不要担心按钮的宽度相同 - 只需拉伸其中一个按钮即可填充剩余的水平空间。 大致就位后,设置以下约束条件。 自动布局将计算其正确的最终位置。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/two_equal-width_buttons_2x.png =364x168) 1. Short Button.Leading = Superview.LeadingMargin 2. Long Button.Leading = Short Button.Trailing + Standard 3. Long Button.Trailing = Superview.TrailingMargin 4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0 5. Bottom Layout Guide.Top = Long Button.Botton + 20.0 6. Short Button.Width = Long Button.Width ### 5.2 属性 为按钮提供可见的背景颜色,以便在设备旋转时更容易看到其框架如何变化。 另外,为按钮使用不同的长度标题,以显示按钮标题不会影响按钮的宽度。 | View | Attribute | Value | | --- | --- | --- | | Short Button | Background | Light Gray Color | | Short Button | Title | short | | Long Button | Background | Light Gray Color | | Long Button | Title | Much Longer Button Title | ### 5.3 讨论 此配方使用按钮的内在高度,但不计算布局时的宽度。 在水平方向上,这些按钮的尺寸是明确的,以便它们具有相同的宽度并填充可用空间。 要查看按钮的内在高度如何影响布局,请将此配方与 Two Equal-Width Views 配方进行比较。 在这个配方中,只有两个垂直约束,而不是四个。 这些按钮还给出了具有非常不同长度的标题,以帮助说明按钮的文字如何影响(或者在这种情况下,不会影响)布局。 > 注意 > 对于这个配方,这些按钮被赋予了浅灰色的背景色,让你看到它们的框架。 通常,按钮和标签具有透明背景,因此很难(如果不是不可能)看到对其 frame 的任何更改。 ## 第六节 三个等宽按钮 此配方扩展了两个等宽按钮配方,以便它使用三个等宽按钮。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Three_Equal-Width_Buttons_screen_2x.png =451x224) ### 6.1 视图和约束 按照图示布置按钮并设置约束。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/three_equal-width_buttons_2x.png =483x281) 1. Short Button.Leading = Superview.LeadingMargin 2. Medium Button.Leading = Short Button.Trailing + Standard 3. Long Button.Leading = Medium Button.Trailing + Standard 4. Long Button.Trailing = Superview.TrailingMargin 5. Bottom Layout Guide.Top = Short Button.Bottom + 20.0 6. Bottom Layout Guide.Top = Medium Button.Bottom + 20.0 7. Bottom Layout Guide.Top = Long Button.Bottom + 20.0 8. Short Button.Width = Medium Button.Width 9. Short Button.Width = Long Button.Width ### 6.2 属性 为按钮提供可见的背景颜色,以便在设备旋转时更容易看到其框架如何变化。 另外,为按钮使用不同的长度标题,以显示按钮标题不会影响按钮的宽度。 | Para | View | Attribute | | --- | --- | --- | | Short Button | Background | Light Gray Color | | Short Button | Title | Short | | Medium Button | Background | Light Gray Color | | Medium Button | Title | Medium | | Long Button | Background | Light Gray Color | | Long Button | Title | Long Button Title | ### 6.3 讨论 添加一个额外的按钮需要添加三个额外的约束(两个水平约束和一个垂直约束)。 记住,你没有使用按钮的内在宽度,所以你至少需要两个水平约束来唯一地指定它的位置和大小。 但是,您使用的是按钮的固有高度,因此您只需要一个额外的约束来指定其垂直位置。 > 注意 > 要快速设置等宽限制,请选择全部三个按钮,然后使用 Interface Builder 的Pin工具创建等宽限制。 Interface Builder 自动创建所有这两个必需的约束。 ## 第七节 两个等距的按钮 从表面上看,这个配方类似于两个等宽按钮配方(请参见屏幕截图)。 但是,在此配方中,按钮的宽度基于最长的标题。 如果有足够的空间,则按钮仅被拉伸,直到它们都与较长按钮的固有内容大小相匹配。 任何额外的空间均匀分布在按钮周围。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Two_Buttons_with_Equal_Spacing_screen_2x.png =451x224) 在 iPhone 上,两个相等宽度按钮和两个具有相等间距布局的按钮在纵向方向上看起来几乎完全相同。 只有当您将设备旋转到横向(或使用更大的设备,如 iPad)时,差异才会变得明显。 ### 7.1 视图和约束 在 Interface Builder 中,拖出并定位两个按钮和三个视图对象。 将按钮放在视图之间,然后如图所示设置约束。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/two_buttons_with_equal_spacing_2x.png =421x217) 1. Leading Dummy View.Leading = Superview.LeadingMargin 2. Short Button.Leading = Leading Dummy View.Trailing 3. Center Dummy View.Leading = Short Button.Trailing 4. Long Button.Leading = Center Dummy View.Trailing 5. Trailing Dummy View.Leading = Long Button.Trailing 6. Trailing Dummy View.Trailing = Superview.TrailingMargin 7. Bottom Layout Guide.Top = Leading Dummy View.Bottom + 20.0 8. Bottom Layout Guide.Top = Short Button.Bottom + 20.0 9. Bottom Layout Guide.Top = Center Dummy View.Bottom + 20.0 10. Bottom Layout Guide.Top = Long Button.Bottom + 20.0 11. Bottom Layout Guide.Top = Trailing Dummy View.Bottom + 20.0 12. Short Button.Leading >= Superview.LeadingMargin 13. Long Button.Leading >= Short Button.Trailing + Standard 14. Superview.TrailingMargin >= Long Button.Trailing 15. Leading Dummy View.Width = Center Dummy View.Width 16. Leading Dummy View.Width = Trailing Dummy View.Width 17. Short Button.Width = Long Button.Width 18. Leading Dummy View.Height = 0.0 19. Center Dummy View.Height = 0.0 20. Trailing Dummy View.Height = 0.0 ### 7.2 属性 为按钮提供可见的背景颜色,以便在设备旋转时更容易看到其框架如何变化。 此外,为按钮使用不同长度的标题。 按钮的大小应根据最长的标题。 | View | Attribute | Value | | --- | --- | --- | | Short Button | Background | Light Gray Color | | Short Button | Title | Short | | Long Button | Background | Light Gray Color | | Long Button | Title | Much Longer Button Title| ### 7.3 讨论 如您所见,约束集变得复杂。 虽然此示例旨在演示特定技术,但在实际应用程序中,您应该考虑使用堆栈视图。 在此示例中,您希望在父视图的 frame 更改时更改空白区域的大小。 这意味着您需要一组相等的宽度约束来控制空白区域的宽度; 但是,您无法在空白区域创建约束。 必须有某种对象,其大小可以约束。 在此配方中,您使用虚拟视图来表示空白区域。 这些视图是UIView类的空实例。 在这个配方中,他们被赋予0点高度以最小化他们对视图层次的影响。 > 注意 > 虚拟视图会给您的布局增加大量成本,因此您应该明智地使用它们。 如果这些视图很大,即使它们不包含任何有意义的信息,它们的图形上下文也会占用大量内存。 > 此外,这些视图参与视图层次结构的响应者链。 这意味着他们会响应消息,如命中测试,这些消息会沿响应器链发送。 如果不小心处理,这些视图可以拦截并响应这些消息,从而产生难以发现的错误。 或者,您可以使用 [UILayoutGuide](https://developer.apple.com/documentation/uikit/uilayoutguide) 类的实例来表示空格。 此轻量级类表示可以参与自动布局约束的矩形框架。 布局指南没有图形上下文,它们不是视图层次结构的一部分。 这使得布局指南非常适合分组项目或定义空白区域。 遗憾的是,您无法在 Interface Builder 中向场景添加布局指南,并且以编程方式创建的对象与基于故事板的场景混合会变得非常复杂。 作为一般经验法则,使用故事板和界面生成器比使用自定义布局指南更好。 此配方使用大于或等于约束来设置按钮周围的最小间距。 必需的约束还保证按钮总是相同的宽度,并且虚拟视图也总是相同的宽度(但是,它们可以是与按钮不同的宽度)。 其余布局主要由按钮的 CHCR 优先级管理。 如果没有足够的空间,虚拟视图会折叠到 0 点宽度,按钮会在它们之间划分可用空间(它们之间的标准间距)。 随着可用空间的增加,按钮会扩展,直到达到较大按钮的固有宽度,然后虚拟视图开始扩展。 虚拟视图继续扩展以填充任何剩余空间。 ## 第八节 两个带有基于类的布局的按钮 该配方使用两组不同的约束。 为 Any-Any 布局安装一个。 这些约束定义了一对等宽按钮,与两个等宽按钮配方相同。 另一组约束安装在 Compact-Regular 布局上。 这些约束定义了一对堆叠的按钮,如下所示。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Buttons_with_Size_Class_Based_Layout_2x.png =451x224) 垂直堆叠的按钮以纵向方式在 iPhone 上使用。 水平行按钮用于其他任何地方。 ### 8.1 视图和约束 完全按照两个等宽按钮配方的布局布局按钮。 在 Any-Any size 类中,设置约束1到6。 接下来,将 Interface Builder 的大小类切换到 Compact-Regular 布局。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/Setting_the_Compact_Regular_Layout_2x.png =257x343) 卸载约束2和约束5,并添加约束7,8和9,如图所示。 ![](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Art/compact-regular_layout_2x.png =439x255) 1. Short Button.Leading = Superview.LeadingMargin 2. Long Button.Leading = Short Button.Trailing + Standard 3. Long Button.Trailing = Superview.TrailingMargin 4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0 5. Bottom Layout Guide.Top = Long Button.Botton + 20.0 6. Short Button.Width = Long Button.Width 7. Long Button.Leading = Superview.LeadingMargin 8. Short Button.Trailing = Superview.TrailingMargin 9. Long Button.Top = Short Button.Bottom + Standard ### 8.2 属性 为按钮提供可见的背景颜色,以便在设备旋转时更容易看到其框架如何变化。 此外,为按钮使用不同长度的标题,以显示按钮标题不会影响按钮的宽度。 | View | Attribute | Value | | --- | --- | --- | | Short Button | Background | Light Gray Color | | Short Button | Title | short | | Long Button | Background | Light Gray Color | | Long Button | Title | Much Longer Button Title | ### 8.3 讨论 Interface Builder 允许您设置特定于大小的类视图,视图属性和约束。 它允许您为宽度和高度指定三种不同尺寸类(紧凑,任意或常规)的不同选项,总共提供九种不同尺寸类。 其中四个对应于设备上使用的最终尺寸等级(Compact-Compact,Compact-Regular,Regular-Compact和Regular-Regular)。 其余是基本大小类,或两个或更多大小类的抽象表示(Compact-Any,Regular-Any,Any-Compact,Any-Regular和Any-Any)。 加载给定大小类的布局时,系统会加载该大小类的最具体设置。这意味着 Any-Any 大小类定义了所有视图使用的默认值。Compact-Any 设置都会影响具有紧凑宽度的所有视图,而 Compact-Regular 设置仅用于具有紧凑宽度和常规高度的视图。当视图的大小类发生变化时(例如,当iPhone从纵向旋转到横向时),系统会自动交换布局并为更改设置动画。 您可以使用此功能为不同的 iPhone 方向创建不同的布局。您也可以使用它来创建不同的 iPad 和 iPhone 布局。特定于大小类的自定义可以根据需要进行扩展或简化。当然,您拥有的变化越多,故事板变得越复杂,设计和维护就越难。 请记住,您需要确保每个可能的 size 类都有一个有效的布局,包括所有基本 size 类。一般来说,选择一个布局作为默认布局通常是最简单的。在任意 size 的类中设计布局。然后根据需要修改最终 size 类。请记住,您可以在更具体的 size 类中添加和删除项目。 对于更复杂的布局,您可能需要在开始之前绘制 9 x 9 网格的 size 类。使用这些尺寸类的布局填充四个角。然后,网格允许您查看跨多个 size 类共享的约束,并帮助您找到布局和 size 类的最佳组合。 有关使用大小类的详细信息,请参阅 [Debugging Auto Layout](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/TypesofErrors.html#//apple_ref/doc/uid/TP40010853-CH22-SW1) 。 >原文地址 >[Views with Intrinsic Content Size ](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/ViewswithIntrinsicContentSize.html#//apple_ref/doc/uid/TP40010853-CH13-SW1)