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

时间:2016-06-13 18:36:15

标签: ios layout view autolayout nslayoutanchor

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

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

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

3 个答案:

答案 0 :(得分:25)

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

我先介绍一下problem

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

enter image description here

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

enter image description here

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

创建布局指南

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

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

    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. 的更多实例
    3. 就像UIView一样,UILayoutGuide 实例拥有所有种类的锚点
    4. 至于为什么不只是创建虚拟UIView并创建UILayoutGuides:"与视图层次结构中添加虚拟视图有很多相关的成本。首先,创建和维护视图本身是成本。其次,虚拟视图是视图层次结构的完整成员,这意味着它会增加层次结构执行的每个任务的开销。最糟糕的是,隐形虚拟视图可以截取用于其他视图的消息,从而导致很难找到的问题。"
    5. enter image description here

      有关详情,请参阅documentation

      topLayoutGuidesafeAreaLayoutGuide

      topLayoutGuide(已弃用)

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

      的实例

      如果约束到view.topAnchor即:

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

      enter image description here tableView 不会从navigationBar底部开始

      如果约束为topLayoutGuide.bottomAnchor,即:

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

      enter image description here tableView从navigationBar的底部开始

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

        

      我们的想法是,您可以边缘地展示自己的内容。和   它会使酒吧重叠,这样你就可以得到这些漂亮的彩色   通过栏目模糊你的内容

           

      有关详情,请参阅此moment from WWDC和此问题here。我不认为解决方案是完全相关的,只是问题中的图像。

      safeAreaLayoutGuide

        自iOS11 以来

           

      Apple已弃用topLayoutGuide& bottomLayoutGuide。所以   而不是有2个虚拟盒子,你现在有一个名为的虚拟盒子   UIView实例上的safeAreaLayoutGuide。 UIViewController不再有任何这个......   从useyourloaf复制的视觉比较:   enter image description here

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

      有关safeAreaLayoutGuide的更多信息,我高度建议您设置Apple's article on: Positioning Content Relative to the Safe Area

      注意: safeAreaLayoutGuide是UIView属性。 topLayoutGuide是UIViewController属性。

      layoutMarginsGuide

      • UIView只有一个虚拟框。该属性名为layoutMarginsGuide。但与UIViewController不同的是,它并不位于顶部或底部。它只是位于中心,有8个点填充/插入(从所有4个边)到UIView那么这在哪里有用?如果你你会使用它>不要希望将textView约束到UIView实例的边缘。这将改善阅读体验。或者不是将按钮限制在其超级视图的leadingAnchor并使其看起来很丑,而是向锚点添加8个点...即将按钮约束到leadingAnchor然后添加8个常量点。 严格的文字,实际上是您使用readableContentGuide的地方,layoutMarginsGuide非常有用,如果您不希望按钮或标签锚定超级视图的边缘

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

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

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

        另请参阅提供的示例   documentation。   可以找到一个很好的Raywenderlich教程   here

      readableContentGuide

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

          

        此布局指南定义了一个可以轻松读取的区域   强迫用户移动他们的头来跟踪线

        有关详情,请参阅this moment from WWDC: building Adaptive layout和这个真棒useyourloaf tutorial

          

        在纵向iPhone 7 Plus上,可读内容指南是相同的   作为视图的边缘指南,但在景观中有更多的白色   文本视图两侧的空格。在iPad上的风景,   白色空间显着增加。

             

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

             

        来自RayWenderlich

      在下面的图片中,青色固定在layoutMarginGuide上,但绿色固定在readableContentGuide上:

      enter image description here

      UIEdgeInsets

      如果您想更改layoutMarginsGuide即将所需的保证金从8点更改为16点,则必须更改layoutMargins的值,然后更改layoutMarginsGuide& #39; s anchors 会自动更新。 UIEdgeInsets只是layoutMargins类型layoutMarginsUIView

      的属性名称
      someview.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50)
      

      我发现此代码唯一的地方☝️在viewDidLayoutSubviews内有效。有关详情,请参阅here

      Anchors

      他们是基础但没什么特别之处。它们是任何UIView / UILayoutGuide的最远边缘。 UIView和UILayoutGuide实例都有它。 一切你的约束最终会被使用锚点限制,这只是你正在锚定它的实体的锚点的问题。它可以是safeAreaLayoutGuide的锚点,也可以是layoutMarginGuide的锚点,它可以是topLayoutGuide的锚点,也可以是view的锚点。layoutMarginsGuide&#39}一个Anchors的锚点。 (虽然你也可以将你的heightAnchor锚定到50,所以在这种情况下,没有另一个锚点)

      safeAreaLayoutGuidelayoutMarginGuide之间的精彩视觉比较可以从answer找到。它使用故事板完成,因此更容易理解。

      contentInsets

      虽然理解很重要,但这是一个完全不同的讨论,与其他人没有任何关系。它特定于UIScrollViews。有关详情,请参阅this great article

      结论

      为确保安全,确保所有内容 您的视图使用readableContentGuide。如果您想使用系统提供的边距来获得更好的视图布局或者使用一些填充,请使用readableContentGuide,如果您想让事情更具可读性layoutMarginGuide

      layoutMarginGuide的大小始终小于或等于safeAreaLayoutGuide layoutMargins的大小始终小于或等于safeAreaLayoutGuide

      readableContentGuide与CSS的填充非常相似。 contentInset类似于CSS边框。我不知道contentOffset

      是否有任何CSS等价物

      附录:ContentInset与contentOffset

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

答案 1 :(得分:5)

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

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

  1. alignment rects. alignment rects.

  2. content inset and offset example 2 content insets content offest another example

  3. margins margins

答案 2 :(得分:0)

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

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

  1. 考虑消除最难维护/调试/理解的选项
    • 想象一下,有些全新的人加入你的团队,或者有人继承你的代码 - 他们的调试难以实现,为什么会这样?
  2. 考虑消除使布局更难以重新排列/扩展/编辑的选项
  3. 考虑删除与应用程序其余部分不一致的选项(这种情况可以追溯到第一点)
  4. 考虑消除违背Apple意图的选项(请参阅docs / WWDC会谈以了解他们的意图)。
  5. 团队可以通过这个标准共同努力,就我们如何布局我们的UI"在每个场景中。我想你要求的是这种讨论的总和产品:各种布局风格的指南。

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

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

    UILayoutGuide上:

      

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

         

    ...

         

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

    layoutMargins上:

      

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

    directionalLayoutMargins上:

      

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

    contentInset上:

      

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

    topAnchor上:

      

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

    NSLayoutAnchor

      

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