69

我试图弄清楚如何使用自动布局(iOS6)和约束来做到这一点。

基本上,我的大视图在底部分为两个部分。在这些部分(当前为子视图)中,我有一个图像视图和一个标签。我想用可变长度的文本将它们放在两边的中心。

我的头主要是围绕自动布局,但我不确定最好的方法。我倾向于认为这在 IB 中是不可能的,但在代码中是不可能的。

将继续尝试解决这个问题,但与此同时,这是我正在尝试创建的示例。

在此处输入图像描述

4

8 回答 8

67

这就是你所追求的吗?

短标签 长标签

我通过viewCenteredInLeftSection在您的 中添加一个视图(名为 )leftSection,然后将时钟图像和标签添加为具有这些约束的子视图来做到这一点:

  • 使viewCenteredInLeftSection的 CenterX 和 CenterY 等于其父视图的 ( leftSection)。
  • 使clockImage的顶部、底部和前缘等于其父视图的 ( viewCenteredInLeftSection)。
  • 使label的后沿等于其父视图的 ( viewCenteredInLeftSection)。
  • clockImage's Trailing edge 设为距 'sleading edge 的标准距离label

viewCenteredInLeftSection

我在 Interface Builder 中调整 iOS UIViews 的大小时遇到​​了麻烦,所以我为 OS X 制作了我的示例,并且我能够完全在 Interface Builder 中这样做。如果您在 Interface Builder 中制作上述约束时遇到问题,请告诉我,我将发布创建它们的代码。

2014-08-26 编辑

Luda,这里是 Xcode 5 的 Pin 和 Align 菜单,也可以在 Xcode 的菜单栏中找到:

对齐菜单 固定菜单

下面是我的示例在 Interface Builder 中的样子。蓝色视图是原始问题的“父视图”,即图像和标签应居中的给定视图。

我将绿色视图(我命名为viewCenteredInLeftSection)添加为“父视图”的子视图。然后我突出显示它并使用对齐菜单“容器中的水平中心”和“容器中的垂直中心”来创建约束来定义其位置。

我将时钟图像添加为 的子视图viewCenteredInLeftSection,并带有定义其宽度和高度的约束。我突出显示了时钟图像viewCenteredInLeftSection,然后使用 Align > Leading Edges、Align > Top Edges 和 Align > Bottom Edges 应用约束。

我将标签添加为 的子视图viewCenteredInLeftSection,将其定位为距时钟图像的标准 Aqua 空间距离。我突出显示了标签viewCenteredInLeftSection,然后使用对齐 > 后沿应用了约束。

与 Xcode 4 相比,使用 Xcode 5的Interface Builder容易创建。

界面生成器

于 2013-02-07T15:32:33.950 回答
29

我想出了一个不添加另一个视图的方法:

 [aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnLeft attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
 [aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnRight attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];

您还可以更改常量以在视图之间创建间隙。

  • 左视图约束常数:-X
  • 右视图约束常数:+X

居中子视图

于 2013-02-08T01:11:17.810 回答
17

斯坦福大学关于 ios 7 的讲座中考虑了一个解决方案。它工作得很好。附上这个解决方案。(这里 sdfssfg... 东西是 label1 和 efsdfg.... 东西是 label2)

在此处输入图像描述

于 2015-05-02T04:19:06.843 回答
16

我花了一点时间,但我想出了一个非常可靠的解决方案。我想出了 John Sauer 提供的相同解决方案,但不想添加另一个视图来包装它们。

答案需要三个步骤。

1) 包含其他两个的子视图的宽度,我称之为leftInfoSection,需要由它的内容来确定。这消除了它对超级视图(或其他视图)具有左右约束以确定其宽度的需要。这是一个真正的关键,其中很多东西是让孩子定义宽度。

在此处输入图像描述

2)我仍然必须在 IB 中有一个领先的约束,它才能有一个有效的布局。(它需要知道leftInfoSection水平放置的位置)。将该约束连接到您的代码中,以便您可以删除它。除此之外,我还有一个尾随约束 GTE 垂直分隔线 + 3。

3)最后一个关键是考虑你必须使用哪些信息(在代码中,因为 IB 是有限的)。我意识到我知道我的部分上方水平分隔线的中心,并且我的中心leftInfoSection将是该水平条的中心减去水平条宽度的 1/4。这是左侧和右侧的最终代码:

// remove the unwanted constraint to the right side of the thumbnail
[self.questionBox removeConstraint:self.leftInfoViewLeadingConstraint];
// calculate the center of the leftInfoView
CGFloat left = self.horizontalDividerImageView.frame.size.width/4 * -1;
// constrain the center of the leftInfoView to the horizontal bar center minus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.leftInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:left]];

// remove the unwanted constraint to the right side of the questionBox
[self.questionBox removeConstraint:self.rightInfoViewTrailingConstraint];
// calculate the center of the rightInfoView
CGFloat right = left * -1;
// constrain the center of the rightInfoView to the horizontal bar center plus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.rightInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:right]];

结果: 最后结果

此外,IB 对它如何自动更新约束可能非常烦人。当我试图将子视图上的前导和尾随约束定义为 0 时,它会不断断开一个或另一个并对父视图进行约束以定义宽度。诀窍是暂时保留不需要的约束,但将其优先级降低到 999。然后我能够创建子视图约束来定义宽度。

于 2013-02-07T18:41:01.590 回答
11

这很好用,但需要 2 个间隔 UIView:

UIView *spacer1 = [[UIView alloc] init];
spacer1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer1];

UIView *spacer2 = [[UIView alloc] init];
spacer2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer2];

NSDictionary *views = NSDictionaryOfVariableBindings(spacer1, spacer2, imageView, label);

[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[spacer1(>=0)][imageView]-4-[label][spacer2(==spacer1)]|" options:0 metrics:nil views:views];

for (int i = 0; i < constraintsArray.count; i++) {

    [self.view addConstraint:constraintsArray[i]];
}
于 2013-11-16T07:38:15.977 回答
6

在 iOS 9 之后,实现此目的的另一个选择是使用Stack Views

于 2015-12-23T19:31:20.203 回答
0

有几种方法可以做到这一点。基本来说,这里是如何将 1..n 个项目居中,假设所有项目的大小都受到限制并且不会增长

  1. 在物品的每一侧放置 2 个垫片。将垫片锚定到父边。将您的第一个和最后一个项目锚定到锚点上。最后,指定 1 个垫片具有另一个垫片的宽度。您不需要显式设置任何垫片大小,因为它将被解决

    • spacer1 -> left=parent:left width=spacer2:width
    • spacer2 -> 右=父:右
    • yourFirstItem -> left=spacer1:right
    • yourLastItem -> 右=spacer2:left
  2. 如果垫片不是您的东西,并且您和您有奇数个项目,则将中间一个放在父项的中心。此外,请确保第一个和最后一个项目没有锚定到父边缘。

    • yourMiddleItem = centerX=parent:centerX
    • otherItems->yourMiddleItem<-otherItems
  3. 如果垫片不是您的东西,并且您有偶数个项目,则将 2 个内部项目的边缘居中到父项的中心。此外,请确保第一个和最后一个项目没有锚定到父边缘。

    • leftMiddleItem -> right=parent:centerX
    • rightMiddleItem -> left=parent:centerX
    • otherItems->leftMiddleItem rightMiddleItem<-otherItems
  4. 你也可以在中心放置一个不可见的占位符,并锚定到该位置,但是在约束时你仍然需要考虑奇数/偶数的项目,所以我不推荐这种方法。

于 2017-12-09T14:06:59.997 回答
-1

你可能想参考这个

基于百分比的标记

基本上,它说首先使用一些不正确的边距,然后将其更正到其父视图。

处理我的情况。

于 2015-08-25T14:50:28.020 回答