在iOS上,边距,边缘插入,内容插入,对齐方式,布局边距,锚点​​之间有什么区别......?

kra*_*eon 26 layout view ios autolayout nslayoutanchor

似乎有几个不同的选项/术语,iOS社区中的人在布局方面使用(例如,UIEdgeInsets是一种类型,但有时我会听到/读取"设置插图"或布局边距与布局指南).

我总能找到一个有效的选项.但我不确定我是否正在使用合适的工具.

有人可以帮助在布局的这些不同方面之间提供一些清晰度,以及何时以最佳方式使用每个方面?

Hon*_*ney 29

作为赏金提供者...我会说我的大部分困惑来自于不正确地理解UILayoutGuide课程.这是关键,但也很简单.

我先来介绍一个问题:

在过去,如果你需要像这样限制这些圈子:

在此输入图像描述

然后你必须创建清晰的 UIViews并将它们添加为子视图,然后将约束添加到它们,如下所示:

在此输入图像描述


今天,您无需将它们添加为子视图.你可以改为

创建布局指南

要创建布局指南,您必须执行以下步骤:

  1. 实例化新的布局指南.
  2. 通过调用视图的addLayoutGuide(_:)方法将布局指南添加到视图中.
  3. 使用"自动布局"定义布局指南的位置和大小.您可以使用这些参考线来定义布局中元素之间的空间.以下示例显示了用于在一系列视图之间定义相等间距的布局指南.

脚步:

let space1 = UILayoutGuide()
view.addLayoutGuide(space1)

let space2 = UILayoutGuide()
view.addLayoutGuide(space2)

space1.widthAnchor.constraintEqualToAnchor(space2.widthAnchor).active = true
saveButton.trailingAnchor.constraintEqualToAnchor(space1.leadingAnchor).active = true
cancelButton.leadingAnchor.constraintEqualToAnchor(space1.trailingAnchor).active = true
cancelButton.trailingAnchor.constraintEqualToAnchor(space2.leadingAnchor).active = true
clearButton.leadingAnchor.constraintEqualToAnchor(space2.trailingAnchor).active = true
Run Code Online (Sandbox Code Playgroud)

布局指南也可以作为黑盒子,包含许多其他视图和控件.这使您可以封装部分视图,将布局分解为模块化块.

三个有趣的笔记:

  1. 如果您正在使用"查看调试层次结构",那么您将看到更多的实例 UILayoutGuide
  2. 就像一个UIView,一个UILayoutGuide 实例拥有所有类型的锚
  3. 至于为什么不只是创建虚拟UIViews并经历创建UILayoutGuides:"在视图层次结构中添加虚拟视图会产生许多成本.首先,创建和维护视图本身需要付出代价.其次,虚拟视图是视图层次结构的完整成员,这意味着它会增加层次结构执行的每个任务的开销.最糟糕的是,不可见的虚拟视图可以截取用于其他视图的消息,从而导致很难找到的问题.

在此输入图像描述

欲了解更多请参阅文档.


topLayoutGuidesafeAreaLayoutGuide

topLayoutGuide(已弃用)

它已被弃用,但出于学习目的:A UIViewController有2个虚拟框.顶部命名的1个属性topLayoutGuide和底部命名的另一个属性bottomLayoutGuide.viewController本身没有左/前或右/尾侧的任何指南.这两个都是一个例子UILayoutGuide

如果约束到view.topAnchor即:

tableView.topAnchor.constraint(equalTo: view.topAnchor)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 tableView 从navigationBar的底部开始

如果约束到topLayoutGuide.bottomAnchorie:

tableView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor) 
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 tableView从navigationBar的底部开始

根据您的布局设计,您可能希望在导航栏下方模糊您的内容.

而这个想法就是你会将你的内容边缘化.它会使酒吧不足以让你通过酒吧获得这些漂亮的彩色模糊内容

欲了解更多看到这个来自WWDC时刻和这个问题在这里.我不认为解决方案是完全相关的,只是问题中的图像.

safeAreaLayoutGuide

从iOS11开始

Apple已弃用topLayoutGuide&bottomLayoutGuide.因此,您现在safeAreaLayoutGuide在UIView实例上有1个虚拟框,而不是拥有2个虚拟框 .UIViewController不再具有任何此类...从useyourloaf复制的视觉比较: 在此输入图像描述

旁注:如果您使用故事板,那么将您的视图与topLayoutGuide或safeAreaLayoutGuide顶部对齐将呈现相同的效果.如果您不使用故事板(以编程方式执行),那么您必须在iOS11和LessThaniOS11之间跳舞并拥有2个不同版本的代码

有关更多信息safeAreaLayoutGuide,我强烈建议您将Apple的文章设置为:相对于安全区域定位内容


safeAreaLayoutGuide

  • topLayoutGuide只有一个假盒子.该物业的名称layoutMarginsGuide.但不像UIView它不坐在顶部或底部.它只是位于中心,有8个点填充/插入(从所有4个边)到layoutMarginsGuide.那么它在哪里有用?:如果您希望将textView约束到UIView实例的边缘,则可以使用此方法.这将改善阅读体验.或者不是将按钮限制在其超级视图的leadingAnchor并使其看起来很丑,而是向锚点添加8个点...即将按钮约束到leadingAnchor然后添加8个常量点.该删除线的文本,实际上,你会用的UIViewController,UIView如果当你不希望你的按钮或标签是非常有用的锚定到它的父的边缘

    someButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8)
    
    Run Code Online (Sandbox Code Playgroud)

    但等待有一个更简单的方法.只需使用Apple建议的保证金即使用:

    someButton.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor)
    
    Run Code Online (Sandbox Code Playgroud)

    另请参阅文档中提供的示例 .可以在这里找到一个好的Raywenderlich教程


readableContentGuide

  • 略有不同layoutMarginsGuide.两者都是UIView的属性.有时他们是相同的,有时他们不是.它的目的是:

    此布局指南定义了一个可以轻松读取的区域,而无需强制用户移动头部来跟踪线条

    有关更多信息,请参阅WWDC的这一时刻:构建自适应布局和这个非常棒的useyourloaf教程.

    在纵向的iPhone 7 Plus上,可读的内容指南与视图的边距指南相同,但在横向上,文本视图的两侧有更多的空白区域.在横向的iPad上,白色空间显着增加.

    边距大小取决于系统的动态类型.字体越大,指南越宽.

    来自RayWenderlich

在下面的图像中,青色锚定到readableContentGuide,但绿色锚定到layoutMarginGuide:

在此输入图像描述


layoutMarginGuide

如果你想改变你的readableContentGuideie,将所需的边距从8点改为16点,那么你必须改变它UIEdgeInsets的值,然后你layoutMarginsGuide锚点会自动更新. layoutMargins只是你的类型layoutMarginsGuide.UIEdgeInsets是属性的的layoutMargins

someview.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50)
Run Code Online (Sandbox Code Playgroud)

我发现这个代码唯一的地方☝️才有效果layoutMargins.更多请看这里


UIView

它们是基础但没有什么特别之处.它们是任何UIView/UILayoutGuide的最远边缘.UIView和UILayoutGuide实例都有它.一切你限制使用锚,最终的限制,它只是一个对事情有什么你是它锚定到实体的锚.这可能是一个viewDidLayoutSubviews的锚,它可能是一个Anchors的锚,它可能是一个safeAreaLayoutGuide的锚它可能是一个layoutMarginGuide的锚.(虽然您也可以将heightAnchor锚定为50,所以在这种情况下没有其他锚点)

一个伟大之间的视觉对比topLayoutGuide,并view从这里可以找到答案.它使用故事板完成,因此更容易理解.


layoutMarginsGuide

虽然理解很重要,但这是一个完全不同的讨论,与其他人没有任何关系.它特定于UIScrollViews.有关更多信息,请参阅此文章


结论

为了安全起见,确保所有内容都您的视图中使用Anchors.如果你想使用系统提供的边距来获得更好的视图布局或者有一些填充,那么使用contentInsets,如果你想让事情更具可读性safeAreaLayoutGuide.

所述layoutMarginGuide的尺寸始终是小于或等于readableContentGuide.
所述readableContentGuide的尺寸始终是小于或等于layoutMarginGuide

layoutMarginGuide与CSS的填充非常相似.safeAreaLayoutGuide类似于CSS边框.我不知道是否有任何CSS等价物layoutMargins


附录:ContentInset与contentOffset

它们用于scrollViews,与答案的其余部分有些无关.至于什么safeAreaLayoutGuide&readableContentGuide是,请参阅这一刻从WWDC 2018:UIKit的:应用程序对于每一个的大小和形状 .视频非常简单.另请参阅下面的Karthik的答案.有这样说,你完全理解scrollView如何工作并理解contentInset它是什么是至关重要的,否则它将是复杂的.有关更多内容contentOffset和scrollView,请参阅Vacawama的答案


Kar*_*mar 5

希望您能从以下链接/图片中获取信息。

您将能够从下面的链接中得出关于布局参数的必要信息。

  1. 对齐矩形。 对齐矩形。

  2. 内容插入和偏移 示例2 内容插图 令人讨厌的内容另一个例子

  3. 边距 边距


mat*_*liu 1

抱歉,如果这是一个无聊的答案,但我觉得 Apple 开发人员文档非常擅长描述每个 UIView 属性的使用方式。

\n\n

至于当您有多种可行的方法/选项时,实现布局的最佳方法是什么……这实际上是风格/意见的问题。我会重点考虑以下标准来做出决定:

\n\n
    \n
  1. 考虑消除最难维护/调试/理解的选项\n\n
      \n
    • 想象一下,有人新加入您的团队,或者有人继承您的代码 - 他们在调试哪种实现时会遇到困难,为什么?
    • \n
  2. \n
  3. 考虑消除使布局更难以重新排列/扩展/编辑的选项
  4. \n
  5. 考虑消除与应用程序其余部分不一致的选项(这又回到了第一点)
  6. \n
  7. 考虑消除违背 Apple 意图的选项(请参阅文档/WWDC 会谈以了解他们的意图)。
  8. \n
\n\n

团队可以通过此标准共同努力,就每个场景中“我们如何布局 UI”达成一致。我想您所要求的是此类讨论的总和产物:某种布局风格指南。

\n\n

根据我的经验,这总是在我工作过的团队中有机地发展,并且事情并没有真正写下来。这更多的是上面第 3 点的内容。

\n\n
\n\n

Apple 文档中有关问题中描述的类的一些摘录:

\n\n

在UILayoutGuide上:

\n\n
\n

使用布局指南来替换您可能创建的虚拟视图,以表示用户界面中的视图间空间或封装。传统上,有许多自动布局技术需要虚拟视图。

\n\n

...

\n\n

UILayoutGuide 类旨在执行以前由虚拟视图执行的所有任务,但以更安全、更高效的方式执行。

\n
\n\n

布局边距上:

\n\n
\n

在 iOS 11 及更高版本中,使用 orientationLayoutMargins 属性而不是此属性来指定布局边距。

\n
\n\n

在orientationLayoutMargins上:

\n\n
\n

使用此属性指定此视图与其子视图的边缘之间所需的空间量(以磅为单位测量)。根据当前布局方向,将前边距和尾边距适当地应用于左侧或右侧边距。

\n
\n\n

在contentInset上:

\n\n
\n

使用此属性可以扩展内容和内容视图边缘之间的空间。大小的单位是点。默认值为 UIEdgeInsetsZero。

\n
\n\n

顶部锚点

\n\n
\n

使用此锚点创建带有 view\xe2\x80\x99s 顶部边缘的约束。您只能将此锚点与其他 NSLayoutYAxisAnchor 锚点组合。有关详细信息,请参阅 NSLayoutAnchor。

\n
\n\n

关于NSLayoutAnchor

\n\n
\n

使用这些约束通过自动布局以编程方式定义布局。不要直接创建 NSLayoutConstraint 对象,而是从要约束的 UIView、NSView 或 UILayoutGuide 对象开始,然后选择该对象\xe2\x80\x99s 锚点属性之一。这些属性对应于自动布局中使用的主要 NSLayoutConstraint.Attribute 值,并提供适当的 NSLayoutAnchor 子类来创建对该属性的约束。使用anchor\xe2\x80\x99s 方法来构造约束。

\n
\n

  • 我对文档不感兴趣。我对它的实际用例感兴趣。你会在哪里使用其中一个而不使用另一个。也许提供一些不是正确选择的图像是个好主意 (2认同)
  • 我的问题是我不应该在哪里使用锚点而使用另一个锚点......为什么?我需要一些例子来说明锚点不起作用的情况。 (2认同)