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

似乎有几个不同的选项/术语和iOS社区的人在布局方面使用(例如,UIEdgeInsets是一种types,但有时我听到/读“设置插页”或版面边距vs布局指南)。

我一直能find一个有效的select。 但我不确定我是否正在使用正确的工具。

有人可以帮助提供布局的这些不同方面之间的清晰度,什么时候以最好的方式使用每个方面?

作为OP。 我会说我的大部分困惑来自于不正确地理解UILayoutGuide类。 这是关键,但也很简单。

让我先介绍一个问题 :

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

在这里输入图像说明

然后你必须创build清晰的 UIViews并将它们添加为你的子视图,然后像下面那样添加你的约束:

在这里输入图像说明


今天,您不需要将它们添加为您的子视图。 你可以代替

创build布局指南

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

  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 

布局指南也可以充当一个黑盒子,包含许多其他视图和控件。 这可以让你封装你的视图的一部分,把你的布局分解成模块化的块。

两个有趣的笔记:

  1. 如果你正在使用'查看debugging层次结构',那么你会看到更多的UILayoutGuide实例
  2. 就像一个UIView,一个UILayoutGuide 实例有各种各样的锚

在这里输入图像说明

更多请参阅文档 。


  • topLayoutGuide: UIViewController有2个虚拟框。 顶层名为topLayoutGuide 1个属性以及名为topLayoutGuide底部的另一个属性。 viewController本身没有任何指南左/前或右/尾两侧。 这两个都是UILayoutGuide一个实例

如果限制view.topAnchor即:

 tableView.topAnchor.constraint(equalTo: view.topAnchor) 

在这里输入图像说明 tableView 不会从navigationBar的底部开始

如果限制为topLayoutGuide.bottomAnchor即:

 tableView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor) 

在这里输入图像说明 tableView从navigationBar的底部开始

自iOS11以来

苹果已弃用topLayoutGuidebottomLayoutGuide 。 因此,不是有2个虚拟框, safeAreaLayoutGuide在UIView实例上有1个名为safeAreaLayoutGuide虚拟框。 UIViewController不再有任何这样的…从useyourloaf复制的视觉比较: 在这里输入图像说明


  • layoutMarginsGuide UIView只有一个虚拟框。 该物业被命名为layoutMarginsGuide 。 但不像UIViewController它不坐在顶部或底部。 它只是坐在8点填充/插入(从所有4边)到UIView那么这有用吗? :如果你不想让你的textView被约束到一个UIView实例的边缘,你可以使用它。 这将改善阅读体验。 或者,不要将一个button约束到superview的leadingAnchor,并使其看起来很难看,而是将8个点添加到anchor中,即将button约束到leadingAnchor,然后添加8个常量点。

     someButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8) 

    但是等一下还有一个更简单的方法。 只要使用苹果的build议保证金即使用:

     someButton.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor) 

    另请参阅文档中提供的示例。 一个很好的Raywenderlich教程可以在这里find

  • UIEdgeInsets:如果你想改变你的layoutMarginsGuide即把它从8点改为16点,那么你必须改变layoutMargins的值,然后layoutMarginsGuide会自动更新。 UIEdgeInsets只是你的layoutMarginstypeslayoutMarginsUIView类的属性名称

     someview.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50) 

    唯一的地方,我发现这个代码☝️有其效果是在viewDidLayoutSubviews 。欲了解更多,请参阅这里

  • 不是特别的。 它们是任何UIView / UILayoutGuide的最远端。 UIView和UIlayoutGuide实例都有它。 一切约束最终都是使用锚来约束的,这只是一个问题,你锚定的是哪个实体的锚。 它可能是一个safeAreaLayoutGuide的锚,它可能是一个layoutMarginGuide的锚,它可能是一个topLayoutGuide的锚,它可能是一个view的锚点。 (虽然你也可能只是将你的heightAnchor锚定到50,所以在这种情况下没有另一个锚)

    layoutMarginsAnchors之间的一个很好的比较可以从这个答案中find。 这是使用故事板完成的,因此更容易理解。

  • contentInsets与其他人无关。 欲了解更多,请参阅这篇

结论

为了安全可靠,一切都您的视野内使用safeAreaLayoutGuide 。 如果你想让事情更具可读性或者有一些填充,那么使用layoutMargins

layoutMargins与CSS的填充非常相似。 safeAreaLayoutGuide类似于CSS边框。

我希望你会从下面的链接/图片获取信息。

你将能够从下面的链接推断出所需的布局参数信息。

  1. alignmentrects。 对齐rects。

  2. 内容插入和偏移 示例2 内容插入 内容犯罪 另一个例子

  3. 利润率 利润率

对不起,如果这是一个无聊的答案,但我觉得像苹果开发者文档是很好的描述如何使用每个UIView属性。

至于当你有多种方法/选项的时候,实现布局的最好方法是什么……这真是一个风格/意见的问题。 我将重点放在以下标准上来做出决定:

  1. 考虑消除最难维护/debugging/理解的选项
    • 想象一下,有一些全新的人join你的团队,或者有人inheritance你的代码 – 哪个实现将会有困难,为什么?
  2. 考虑消除使布局难以重新排列/展开/编辑的选项
  3. 考虑消除与其他应用程序不一致的选项(这种情况可以回到第一点)
  4. 考虑消除违背苹果意图的选项(请参阅文档/ WWDC谈话以了解其意图)。

一个团队可以通过这个标准一起工作,在每个场景中就“如何布置我们的用户界面”达成一致。 我想你要求的是这种讨论的总和产品:一种排版风格的指南。

根据我的经验,这对我所从事的团队来说总是有机的发展,事情并没有真正写下来。 上面的第3点是更多的。


以下问题中描述的类的Apple文档摘录如下:

在UILayoutGuide上 :

使用布局指南来replace您可能创build的虚拟视图来表示视图间空间或封装在用户界面中。 传统上,有一些自动布局技术需要虚拟视图。

UILayoutGuide类被devise为执行所有先前由虚拟视图执行的任务,但是以更安全,更高效的方式执行。

在layoutMargins上 :

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

在directionalLayoutMargins上 :

使用此属性可指定此视图及其子视图的边缘之间所需的空间量(以点为单位)。 根据当前布局方向,前后页边距适用于左侧或右侧页边距。

在contentInset上 :

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

顶部Anchor :

使用此锚可以为视图的顶部边缘创build约束。 您可以将此锚仅与其他NSLayoutYAxisAnchor锚相结合。 有关更多信息,请参阅NSLayoutAnchor。

在NSLayoutAnchor

使用这些约束可以使用自动布局以编程方式定义您的布局。 直接创buildNSLayoutConstraint对象,而不是直接创build一个你想约束的UIView,NSView或UILayoutGuide对象,然后select一个对象的锚定属性。 这些属性对应于自动布局中使用的主NSLayoutConstraint.Attribute值,并提供一个适当的NSLayoutAnchor子类来为该属性创build约束。 使用锚的方法来构造你的约束。