在 iOS 上,边距、边缘插入、内容插入、对齐矩形、布局边距、锚点...之间有什么区别? [英] On iOS, what are the differences between margins, edge insets, content insets, alignment rects, layout margins, anchors...?

查看:15
本文介绍了在 iOS 上,边距、边缘插入、内容插入、对齐矩形、布局边距、锚点...之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我总能找到有效的选项.但我不确定我是否使用了正确的工具来完成这项工作.

有人可以帮助澄清布局的这些不同方面以及何时以最佳方式使用每个方面吗?

解决方案

请参阅

然后你必须创建clear UIViews 并将它们添加为你的子视图,然后像下面这样向它们添加约束:


今天您不需要将它们添加为您的子视图.你可以改为使用

布局指南

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

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

步骤:

let space1 = UILayoutGuide()view.addLayoutGuide(space1)让 space2 = UILayoutGuide()view.addLayoutGuide(space2)space1.widthAnchor.constraintEqualToAnchor(space2.widthAnchor).active = truesaveButton.trailingAnchor.constraintEqualToAnchor(space1.leadingAnchor).active = truecancelButton.leadingAnchor.constraintEqualToAnchor(space1.trailingAnchor).active = truecancelButton.trailingAnchor.constraintEqualToAnchor(space2.leadingAnchor).active = trueclearButton.leadingAnchor.constraintEqualToAnchor(space2.trailingAnchor).active = true

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

三个有趣的笔记:

  1. 如果您使用的是查看调试层次结构",那么您将看到更多 UILayoutGuide
  2. 实例
  3. 就像 UIView 一样,UILayoutGuide 实例具有所有类型的锚
  4. 至于为什么不只是创建虚拟 UIView 并通过创建 UILayoutGuides:将虚拟视图添加到您的视图层次结构会产生许多相关的成本.首先,创建和维护视图本身是有成本的.其次,虚拟视图是视图层次结构的完整成员,这意味着它会增加层次结构执行的每个任务的开销.最糟糕的是,不可见的虚拟视图可能会拦截打算发送给其他视图的消息,从而导致很难发现的问题."

有关更多信息,请参阅tableView 从导航栏的底部开始.注意导航栏后面的橙色...

但是,如果您将其限制为 topLayoutGuide.bottomAnchor 即:

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

然后tableView从navigationBar底部开始

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

<块引用>

这个想法是你可以边对边显示你的内容.和它会覆盖在酒吧下面,这样你就可以得到这些漂亮的彩色通过栏与您的内容模糊

有关详情,请参阅

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

有关 safeAreaLayoutGuide 的更多信息,我强烈建议您设置

UIEdgeInsets

如果你想改变你的 layoutMarginsGuide,即将所需的边距从 8 点改为 16 点,那么你必须改变 layoutMargins 的值,然后是 layoutMarginsGuideanchors 会自动更新.UIEdgeInsets 只是你的 layoutMarginstype.layoutMarginsUIView

的一个属性name

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

我发现这段代码 ☝️ 起作用的唯一地方是在 viewDidLayoutSubviews 内.有关更多信息,请参阅 这里

锚点

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

layoutMarginsGuideAnchors 之间的很好的视觉比较可以从这个 答案.它使用故事板完成,因此更易于理解.


contentInsets

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


结论

为了安全并确保一切都你的视图使用safeAreaLayoutGuide.如果您想使用系统提供的边距来更好地布局视图或有一些填充,请使用 layoutMarginGuide,如果您想让事情更具可读性 readableContentGuide.

readableContentGuide 的大小总是小于或等于 layoutMarginGuide.
layoutMarginGuide 的大小总是小于或等于 safeAreaLayoutGuide

layoutMargins 与 CSS 的 padding 非常相似.safeAreaLayoutGuide 类似于 CSS 边距.我不知道 readableContentGuide

是否有任何等效的 CSS

附录:ContentInset 与 contentOffset

它们用于滚动视图,与答案的其余部分无关.至于什么contentInset &contentOffset 是,请看 这一刻来自WWDC 2018:UIKit:适用于各种尺寸和形状的应用程序.视频非常简单.另请参阅下面 Karthik 的回答.话虽如此,您必须完全了解 scrollView 的工作原理并了解 contentSize 是什么,否则会很复杂.有关 contentSize 和 scrollView 的更多信息,请参见 Vacawama 的回答

There seem to be several different options/terms and people in the iOS community use with respect to layout (e.g. UIEdgeInsets is a type, but sometimes I hear/read "set the insets" or layout margins vs layout guides).

I've always been able to find an option that works. But I'm never sure that I'm using the right tool for the job.

Can someone help provide some clarity between these different aspects of layout and when to use each in the best way?

解决方案

See this UIKit: Apps for Every Size and Shape before and after reading this. Might also want to see the notes from here as well.

Being the Bounty offerer...I'd say the majority of my confusion came from not properly understanding the UILayoutGuide class. That is key, but also very simple.

Let me first introduce a problem:

In the old days, if you needed to constrain these circles like this:

Then you had to create clear UIViews and add them as your subviews and then add your constraints to them like below:


Today you don't need to add them as your subviews. You could instead just use

Layout Guides

To create a layout guide, you must perform the following steps:

  1. Instantiate a new layout guide.
  2. Add the layout guide to a view by calling the view’s addLayoutGuide(_:) method.
  3. Define the position and size of the layout guide using Auto Layout. You can use these guides to define the space between elements in your layout. The following example shows layout guides used to define an equal spacing between a series of views.

steps:

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

Layout guides can also act as a black box, containing a number of other views and controls. This lets you encapsulate part of your view, breaking your layout into modular chunks.

Three interesting notes:

  1. If you are using the 'view debug hierarchy' then you would be seeing more instances of UILayoutGuide
  2. Just like a UIView, a UILayoutGuide instance has all kinds of anchors
  3. As for why not just create dummy UIViews and going through creating UILayoutGuides: "There are a number of costs associated with adding dummy views to your view hierarchy. First, there is the cost of creating and maintaining the view itself. Second, the dummy view is a full member of the view hierarchy, which means that it adds overhead to every task the hierarchy performs. Worst of all, the invisible dummy view can intercept messages that are intended for other views, causing problems that are very difficult to find."

For more see documentation.


topLayoutGuide vs. safeAreaLayoutGuide

topLayoutGuide (deprecated)

It's deprecated for but for learning purposes: A UIViewController has 2 dummy boxes. 1 property at the top named topLayoutGuide and another property at the bottom named bottomLayoutGuide. The viewController itself doesn't have any guides for its left/leading or right/trailing sides. Both of these are an instance of UILayoutGuide

if constrained to view.topAnchor ie:

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

tableView doesn't start from the bottom of the navigationBar. Notice the orange behind the navigationBar...

However if you constrained it to topLayoutGuide.bottomAnchor ie:

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

then tableView starts from the bottom of the navigationBar

And depending on your layout design you might want your content to be blurred below the navigation bar.

And the idea was that you would display your content edge to edge. And it would underlap the bars so that you could get these nice colorful blurs with your content through the bars

For more see this moment from WWDC and this question here. I don't think the solutions are exactly related, just the image in the question.

safeAreaLayoutGuide

since iOS11

Apple has deprecated topLayoutGuide & bottomLayoutGuide. So instead of having two dummy boxes, you now have one dummy box named safeAreaLayoutGuide on the UIView instance. UIViewController no longer has any of this... A visual comparison copied from useyourloaf:

side note: If you use storyboards then aligning your views to the topLayoutGuide or top of safeAreaLayoutGuide would render the same. If you don't use storyboards (do it programmatically) then you would have to dance between iOS11 and and LessThaniOS11 and have 2 different versions of code

For more on safeAreaLayoutGuide, I highly recommend that you set Apple's article on: Positioning Content Relative to the Safe Area

NOTE: safeAreaLayoutGuide is a UIView property. topLayoutGuide is a UIViewController property.


layoutMarginsGuide

  • UIView has only 1 dummy box. The property is named layoutMarginsGuide . But unlike UIViewController it doesn't sit at the top or bottom. It just sits at the center with 8points padding/inset (from all 4 sides) into the UIView.So where is this useful?: You would use this if you don't want your textView to be constrained to the edges of a UIView instance. This would improve the reading experience. Or instead of constraining a button to the leadingAnchor of its superview and making it look ugly, you add 8 points to the anchor...ie constraint the button to the leadingAnchor and then adding 8 constant points. The striked text, is actually where you would use readableContentGuide, layoutMarginsGuide is useful if for when you don't want your button or label anchored to the edge of its superview

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

    But wait there is an easier way. Just use Apple's recommended margin ie use:

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

    Also see the example provided in

documentation. A good Raywenderlich tutorial can be found here

readableContentGuide

  • Is slightly different from layoutMarginGuide. Both are properties of UIView. Sometimes they are identical sometimes they aren't. It's purpose is:

    This layout guide defines an area that can easily be read without forcing users to move their head to track the lines

    For more see this moment from WWDC: building Adaptive layout and this awesome useyourloaf tutorial.

    On the iPhone 7 Plus in portrait, readable content guides are the same

as the view’s margin guides, but in landscape there is more white space on either side of the text view. On the iPad in landscape, the white space is increased significantly.

The margin size depends on the system’s dynamic type. The larger the font, the wider the guide will be.

From RayWenderlich

In the image below the cyan is anchored to the layoutMarginGuide, but the green is anchored to the readableContentGuide:

UIEdgeInsets

If you want to change your layoutMarginsGuide ie change the desired margin from 8 points to 16 points then you must change the layoutMargins's value and then the layoutMarginsGuide's anchors would get automatically updated. UIEdgeInsets is just the type of your layoutMargins. layoutMargins is a property name of the UIView class

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

The only place I found this code ☝️ to have its effect is inside viewDidLayoutSubviews.For more see here

Anchors

They're foundational but nothing special to it. They are the farthest edge of any UIView/UILayoutGuide. Both UIView and UILayoutGuide instances have it. EVERYTHING you constrain is eventually constrained using anchors, it's just a matter of to what entity's anchors you are anchoring it to. It could be a safeAreaLayoutGuide's anchor, it could be a layoutMarginGuide's anchor, it could be a topLayoutGuide's anchor it could be a view's anchor. (though you may also just anchor your heightAnchor to 50, so in that case there isn't another anchor)

A great visual comparison between layoutMarginsGuide and Anchorscan be found from this answer. It's done using storyboards so it makes it easier to understand.


contentInsets

While it's important to understand, is a totally different discussion and has nothing to do with the others. It's specific to UIScrollViews. For more see this great article


Conclusion

To be safe and sure everything is inside your view use safeAreaLayoutGuide. If you want to use the system provided margins to have better layout of views or have some of padding then, use layoutMarginGuide, if you want to make things more readable readableContentGuide.

The readableContentGuide's size is always smaller or equal to layoutMarginGuide.
The layoutMarginGuide's size is always smaller or equal to safeAreaLayoutGuide

layoutMargins is very similar to CSS's padding. safeAreaLayoutGuide is similar to CSS margins. I don't know if there is any CSS equivalent for readableContentGuide


Addendum: ContentInset vs. contentOffset

They are for scrollViews, and somewhat unrelated to the rest of the answer. As for what contentInset & contentOffset are, please see this moment from WWDC 2018: UIKit: Apps for Every Size and Shape . The video is very simple. Also refer to Karthik's answer below. Having that said it's vital that you fully understand how a scrollView works and understand what contentSize is, otherwise it would be complicated. For more on contentSize and scrollView see Vacawama's answer here

这篇关于在 iOS 上,边距、边缘插入、内容插入、对齐矩形、布局边距、锚点...之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆