在iOS上,边距,边缘插入,内容插入,对齐方式,布局边距,锚点 之间有什么区别......? topLayoutGuide safeAreaLayoutGuide layoutMarginsGuide readableContentGuide UIEdgeInsets Anchors contentInsets

问题描述 投票:22回答:3

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

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

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

ios layout view autolayout nslayoutanchor
3个回答
27
投票

作为赏金提供者...我会说我的大多数困惑来自于没有正确理解UILayoutGuide课程。这是关键,但也很简单。

让我先介绍一下problem

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

enter image description here

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

enter image description here


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

创建布局指南

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

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

enter image description here

有关更多信息,请参阅documentation


topLayoutGuide vs. safeAreaLayoutGuide

topLayoutGuide(已弃用)

它已被弃用,但出于学习目的:UIViewController有2个虚拟盒子。顶部的1个房产名为topLayoutGuide,另一个房产位于底部,名为bottomLayoutGuide。 viewController本身没有左/前或右/尾侧的任何指南。这两个都是UILayoutGuide的一个例子

如果约束到view.topAnchor即:

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

qazxsw poi table View不从导航栏的底部开始

如果约束到enter image description here即:

topLayoutGuide.bottomAnchor

qazxsw poi tableView从导航栏的底部开始

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

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

欲了解更多,请看这个tableView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor) 和这个问题enter image description here。我不认为解决方案是完全相关的,只是问题中的图像。

safeAreaLayoutGuide

since iOS11

Apple已弃用moment from WWDChere。因此,在UIView实例上,您现在有1个名为topLayoutGuide的虚拟框,而不是2个虚拟框。 UIViewController不再具有任何此类...从bottomLayoutGuide复制的视觉比较:safeAreaLayoutGuide

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

有关useyourloaf的更多信息,我强烈建议您设置enter image description here

注意:safeAreaLayoutGuide是UIView属性。 Apple's article on: Positioning Content Relative to the Safe Area是一个UIViewController属性。


safeAreaLayoutGuide

  • topLayoutGuide只有一个假盒子。该物业名为layoutMarginsGuide。但与UIView不同,它并不位于顶部或底部。它只是位于中心,有8个点填充/插入(从所有4个边)到layoutMarginsGuide.So这在哪里有用?: 如果您不希望将textView约束到UIView实例的边缘,则可以使用此方法。这将改善阅读体验。或者不是将按钮限制在其超级视图的leadingAnchor并使其看起来很丑,而是向锚点添加8个点...即将按钮约束到leadingAnchor然后添加8个常量点。 被激活的文本,实际上你将使用UIViewControllerUIView是有用的,如果你不希望你的按钮或标签锚定到其superview的边缘 readableContentGuide 但等待有一个更简单的方法。只需使用Apple建议的保证金即使用: layoutMarginsGuide 另请参阅someButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8) 中提供的示例。一个好的Raywenderlich教程可以找到someButton.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor)

documentation

  • here略有不同。两者都是UIView的属性。有时他们是相同的,有时他们不是。它的目的是: 此布局指南定义了一个可以轻松读取的区域,而无需强制用户移动头部来跟踪线条 欲了解更多信息,请参阅readableContentGuide和这个令人敬畏的layoutMarginGuide。 在纵向的iPhone 7 Plus上,可读的内容指南与视图的边距指南相同,但在横向上,文本视图的两侧有更多的空白区域。在横向的iPad上,白色空间显着增加。 边距大小取决于系统的动态类型。字体越大,指南越宽。 来自this moment from WWDC: building Adaptive layout

在下面的图像中,青色锚定到useyourloaf tutorial,但绿色锚定到RayWenderlich

layoutMarginGuide


readableContentGuide

如果你想改变你的enter image description here,即将所需的边距从8点改为16点,那么你必须改变UIEdgeInsets的值,然后layoutMarginsGuide的锚点会自动更新。 layoutMargins就是你的layoutMarginsGuide的类型。 UIEdgeInsetslayoutMargins类的属性名称

layoutMargins

我发现这个代码☝️唯一有效的地方是UIView。更多请参阅someview.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50)


viewDidLayoutSubviews

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

从这个topLayoutGuide可以找到viewlayoutMarginsGuidecan之间的视觉比较。它使用故事板完成,因此更容易理解。


Anchors

虽然理解很重要,但这是一个完全不同的讨论,与其他人没有任何关系。它特定于UIScrollView。欲了解更多信息,请参阅qazxsw poi


Conclusion

为了安全,确保一切都在您的视野内,请使用answer。如果你想使用系统提供的边距来获得更好的视图布局或者有一些填充,那么使用contentInsets,如果你想让this great article更具可读性。

safeAreaLayoutGuide的大小总是小于或等于layoutMarginGuidereadableContentGuide的大小总是小于或等于readableContentGuide

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


Addendum: ContentInset vs. contentOffset

它们用于scrollViews,与答案的其余部分有些无关。至于layoutMarginssafeAreaLayoutGuide是什么,请参阅readableContentGuide。视频非常简单。另请参阅下面的Karthik的答案。有这样说,你完全理解scrollView如何工作并理解contentInset是至关重要的,否则它会很复杂。有关contentOffset和scrollView的更多信息,请参阅this moment from WWDC 2018: UIKit: Apps for Every Size and Shape


5
投票

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

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

  1. contentSize contentSize
  2. Vacawama's answer here alignment rects. alignment rects. content inset and offsetexample 2
  3. content insets content offest

0
投票

很抱歉,如果这是一个无聊的答案,但我觉得Apple Developer文档非常擅长描述如何使用每个UIView属性。

至于什么是实现布局的最佳方式,当你有多个方法/选项工作时...这真的是一个风格/意见的问题。我将重点关注以下标准来做出决定:

  1. 考虑消除最难维护/调试/理解的选项 想象一下,有人会全新加入您的团队或继承您的代码的人 - 他们的调试难以实现,为什么?
  2. 考虑消除使布局更难以重新排列/扩展/编辑的选项
  3. 考虑消除与应用程序其余部分不一致的选项(这种情况可以追溯到第一点)
  4. 考虑消除违背Apple意图的选项(参见文档/ WWDC会谈以了解他们的意图)。

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

根据我的经验,这一直是我所参与过的团队的有机发展,事情并没有写下来。以下第3点是更多的内容。


Apple文档中针对问题中描述的类的一些摘录:

another example

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

...

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

margins

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

margins

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

UILayoutGuide

使用此属性可扩展内容与内容视图边缘之间的间距。单位是点。默认值为UIEdgeInsetsZero。

layoutMargins

使用此锚点可以使用视图的上边缘创建约束。您只能将此锚点与其他NSLayoutYAxisAnchor锚点组合使用。有关更多信息,请参阅NSLayoutAnchor。

directionalLayoutMargins

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

© www.soinside.com 2019 - 2024. All rights reserved.