使用约束将子视图居中于内容视图

3

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

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

现在我想垂直居中它们(y轴)。我希望按钮视图的顶部和标签视图的底部有相等的间距。
我该如何做到这一点?使用优先级的上下约束?
编辑:
Scott,以下是您建议的代码的效果:
图片:https://istack.dev59.com/BuOov.webp 我尝试将按钮视图和标签之间的间距设置为“-1-”,但没有帮助。这就是我需要的外观:
图片:https://istack.dev59.com/eTVcO.webp 这是我用来实现它的代码:
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-13-[buttonView]-[label]-10-|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(buttonView, label)]];

我的约束条件起作用了,但是它是硬编码的,如果可能的话,我更愿意避免使用。


如果我没记错的话,你不能使用视觉格式来做到这一点,你要用代码来构建约束。 - Lily Ballard
我可以硬编码距离,但如果内容视图需要改变大小,我更喜欢一些更动态的东西。 - Padin215
我不是在说硬编码距离。我是在说,在代码中构建约束会给你提供不能用视觉格式表达的选项。 - Lily Ballard
1个回答

6
为了得到你所要求的精确内容,你需要指定一些具体的限制条件。一个天真的尝试可能会从以下行开始(不要使用以下行):
[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和一个添加到视图中的按钮和标签。 查看gist中的代码。这会产生以下输出:

Example app with my constraints

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

Example app with questioner's constraints

我想知道你的按钮是否有更多的功能(它是自定义类吗?)以及contentView

好的,我试了一下代码,有两个问题:第一个是buttonView最终距离顶部只有2像素,而标签似乎在应该的位置。第二个是似乎NSlayoutFormatAlignAllCenterX确实可以将它们居中。我尝试注释掉两个单独的centerX约束,只留下allCenterX,它们确实被居中了。我会在我的帖子中添加图片。 - Padin215
@Log139 只是为了确认一下,您尝试过只使用我展示的最后4个约束条件,对吧?第一个约束条件会产生像您在第一张图片中看到的结果。如果没有那行代码,而您仍然看到那样的结果,那么我会开始怀疑您按钮的内在大小属性。它可能更高。 - Scott Robertson
@Log139 你可以尝试将NSLayoutAttributeBottom更改为NSLayoutAttributeBaseline,看看是否会有任何变化吗? - Scott Robertson
哈!你原来的代码常量是-4.0,而不是4.0。现在对齐了。谢谢! - Padin215

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接