使用约束以内容视图为中心的子视图

Posted

技术标签:

【中文标题】使用约束以内容视图为中心的子视图【英文标题】:subviews centered in a contentview using constraints 【发布时间】:2013-01-25 21:05:38 【问题描述】:

我有一个包含两个子视图的内容视图。我将子视图垂直堆叠并在内容视图中水平居中(x 轴):

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[buttonView]-[label]" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(buttonView, label)]];

现在我想将它们垂直居中(y 轴)。我希望 buttonView 顶部和标签视图底部的空间相等。

我该怎么做?具有优先级的顶部和底部约束?

编辑:

Scott,您建议的代码如下所示:

我尝试在 buttonView 和标签 -1- 之间设置间距,但没有帮助。 这就是我需要的样子:

这是我用来实现它的代码:

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-13-[buttonView]-[label]-10-|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(buttonView, label)]];

我的约束有效,但是是硬编码的,如果可能的话,我宁愿远离。

【问题讨论】:

IIRC 您不能使用视觉格式来执行此操作,您将不得不使用代码构建约束。 我可以;我可以对距离进行硬编码,但如果内容视图需要更改大小,我更喜欢动态的东西。 我并不是说对距离进行硬编码。我的意思是在代码中构建约束为您提供了无法使用视觉格式表达的选项。 【参考方案1】:

要准确获得所需的内容,您需要指定一些特定的约束条件。天真的尝试可能会以 (不要使用以下行)开头:

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonView]-[label]-|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(buttonView, label)]];

但这会导致按钮和标签被拉伸以满足约束。因此,让我们只告诉系统我们想要什么。我们将从您的代码开始,因为这为我们提供了基本的对齐方式。

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[buttonView]-[label]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(buttonView, label)]];
[contentView addConstraint:[NSLayoutConstraint constraintWithItem:buttonView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:contentView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:-4.0]];
[contentView addConstraint:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:contentView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[contentView addConstraint:[NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:contentView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];

4.0 是从哪里来的?它是默认子视图间距- (8) 的一半,将底部与中心 Y 对齐,但向上一点以使中间对齐。

另外,你会注意到我删除了 NSLayoutFormatAlignAllCenterX,因为此时它没有做任何有意义的事情,实际上并没有将视图与超级视图的中心 X 对齐,只是彼此对齐。

编辑:

我制作了一个简单的示例应用程序,它有一个 ViewController 和一个添加到视图的按钮和标签。 See the code as a gist。这会产生以下输出:

作为比较,这里只是在此应用中使用您的原始约束(这就是为什么我认为 NSLayoutAlignAllCenterX 没有进行居中):

我想知道您的按钮(它是自定义类吗?)和 contentView 是否还有更多功能。

【讨论】:

好的,尝试了代码和两件事:首先是 buttonView 最终距离顶部 2 个像素,并且标签似乎在它应该在的位置。其次,NSlayoutFormatAlignAllCenterX 似乎确实使它们居中。我尝试注释掉两个单独的 centerX 约束并离开 allCenterX 并且它们确实居中。我会在帖子中添加图片。 @Log139 仔细检查一下,您只尝试了我显示的最后 4 个约束,对吧?第一个产生的结果就像您在第一张图片中看到的那样。如果该行不存在并且您看到这样的结果,那么我会开始怀疑您的按钮的固有大小属性​​。它可能更高。 @Log139 你能试试把 NSLayoutAttributeBottom 改成 NSLayoutAttributeBaseline 看看有没有什么变化吗? 哈!您的原始代码中的常量为-4.0,而不是 4.0。这样排列更好。谢谢!

以上是关于使用约束以内容视图为中心的子视图的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式使用自动布局约束在视图中垂直对齐中间的子视图

用于拖动的子视图约束

以编程方式将自动布局约束添加到恒定宽度和高度的子视图

使用 IOS 中的约束将 UIView 中的子视图居中

根据子视图的内容大小调整滚动视图

以编程方式创建的 UIView 的框架为 0