Autolayout - 拉伸视图以填充其父视图

Phi*_*ert 7 objective-c ios autolayout

我在使用autolayout尝试使用子视图填充视图时发现了一些非常奇怪的行为.这个想法非常简单:向视图添加子视图并使其使用父视图的所有宽度.

NSDictionary *views = @{
                        @"subview":subView,
                        @"parent":self
                       };
Run Code Online (Sandbox Code Playgroud)

这不起作用:

[self addConstraints:
      [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview]|" 
                                              options:0 
                                              metrics:nil 
                                                views:views]];
Run Code Online (Sandbox Code Playgroud)

子视图不使用父视图的完整宽度.

但这有效:

[self addConstraints:
      [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview(==parent)]|" 
                                              options:0 
                                              metrics:nil 
                                                views:views]];
Run Code Online (Sandbox Code Playgroud)

我希望两者都能按预期工作.那么为什么第一个例子不起作用呢?这是Apple在以下技术说明中推荐的内容:

https://developer.apple.com/library/ios/technotes/tn2154/_index.html

编辑 :(删除无关信息)

rob*_*off 5

这是您为“第一个示例”发布的约束:

第一种情况

这是您为“第二个示例”发布的约束:

第二种情况

我在这些结构中看到了两个差异,这些差异在图中以红色突出显示:

  1. 第一个(折断)情况在近根UIView0x8433f8f0 上具有约束(0x8433f8f0),将其宽度固定为320点。这是多余的,因为每个底层视图都被限制为160点,并且有足够的约束条件使这些较窄视图的所有祖先的宽度都为320点。

  2. 第二个(有效)案例的约束条件为(0x7eb4a670),将接近底部的UIView0x7d5f3fa0的宽度固定为0x7d5f3270的宽度DetailWeatherView。此约束是多余的,因为3fa0的左侧边缘固定到3270的左侧边缘,而3fa0的右侧边缘被约束到3fa0的右侧边缘。我假设(==parent)谓词添加了此约束。

因此,您可能会认为,每种情况都有一个冗余约束,那又如何呢?没关系吧?

不完全的。在第二种情况下,冗余约束确实是无害的。你可以改变的任何的宽度(或两者)WeatherTypeBoxViewAdditionalWeatherInfoBox,你还是会得到一个独特的解决方案。

在第一种情况下,仅当视图的宽度不变时,冗余约束才是无害。如果在f8f0上更改了320宽度的约束而未在叶视图上更改160宽度的约束,则约束系统将没有解决方案。自动布局将打破解决该系统的约束条件之一,并且很可能会打破320宽度的约束条件。我们可以看到,UIView-Encapsulated-Layout-Width由系统强加了320宽度约束及其注释,以强制此视图层次结构符合某个容器的大小(可能是屏幕大小;或者是容器视图控制器的强加大小)。

我不知道为什么您的第一种情况具有这种额外的顶级约束,而第二种情况却没有。我倾向于相信您更改了导致此差异的其他内容,但是自动版式非常神秘,我也不是100%相信这一点。

如果您的目标是使该视图层次结构填充其容器,并使叶子视图保持相等的宽度,则摆脱叶子视图上的160宽度约束,并在它们之间创建单个等宽约束。


Phi*_*ert 1

这没有按预期工作的原因是:

父视图是UISCrollView,并且水平约束设置为"H:|[contentView]|",scrollview 的 contentSize 会自行调整为 所请求的宽度contentView,而不是相反。因此,自动布局引擎将首先确定父级(scrollview)的尺寸contentView,然后将其 contentSize 调整为相同的宽度。如果contentWidth比父级窄,则它不会拉伸,因为父级(scrollview)的 contentSize 将缩小到 的大小contentView

对于常规视图(不是滚动视图),父视图的宽度是固定的,因此它将首先布局父视图,然后布局子视图。

通过强制 的宽度contentView与父滚动视图的宽度相同,contentView将始终与父滚动视图的宽度相同,这就是我想要的(和预期的)。