自动布局(约束)在父视图中居中显示2个视图

我想弄清楚如何做到这一点与自动布局(iOS6)和约束。

基本上我把我的大视野分为两部分。 里面的部分(目前子视图)我有一个图像视图和标签。 我想以两边为中心,用可变长度的文本。

我的头大部分是围绕自动布局,但我不确定最好的办法。 我倾向于认为这是不可能在IB,但在代码。

继续尝试弄清楚这一点,但在此期间,我正在试图创build这个例子。

在这里输入图像说明

这是你在追求什么?

短标签长标签

我在viewCenteredInLeftSection的部分添加了一个视图(命名为viewCenteredInLeftSection ),然后添加时钟图像和标签作为子视图,这些约束是:

  • 使viewCenteredInLeftSection的CenterX和CenterY等于它的leftSection视图( leftSection )。
  • 使clockImage的Top,Bottom和Leading viewCenteredInLeftSection等于它的viewCenteredInLeftSection视图( viewCenteredInLeftSection )。
  • 使label的后沿等于其viewCenteredInLeftSection视图( viewCenteredInLeftSection )。
  • 使clockImage的后缘与label的前缘保持标准距离。

viewCenteredInLeftSection

我无法在界面生成器中调整iOS UIView的大小,所以我做了OS X的示例,而且我完全可以在界面生成器中完成。 如果在Interface Builder中遇到上述限制时遇到困难,请告诉我,我将发布将会创build它们的代码。

2014-08-26编辑

路达 ,这里是Xcode 5的Pin和Align菜单,也可以在Xcode的菜单栏中find:

对齐菜单Pin菜单

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

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

我添加了时钟图像作为viewCenteredInLeftSection子视图,约束定义其宽度和高度。 我突出显示了时钟图像和viewCenteredInLeftSection ,然后使用“alignment”>“ viewCenteredInLeftSection边”,“alignment”>“ viewCenteredInLeftSection ”和“alignment”>“ viewCenteredInLeftSection应用约束。

我将标签添加为viewCenteredInLeftSection的子视图,将其定位为与时钟图像的标准Aqua空间距离 。 我突出标签和viewCenteredInLeftSection ,然后应用约束使用Align> Trailing Edges。

使用Xcode 5的Interface Builder与Xcode 4相比,这样做容易。

界面生成器

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

  [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]]; 

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

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

集中子视图

我花了一段时间,但我find了一个非常稳固的解决scheme。 我想出了约翰·绍尔提供的同样的解决scheme,但不想增加另一种观点来包装这些解决scheme。

答案需要三步。

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

在这里输入图像说明

2)我仍然必须在IB有主要的约束,因为它有一个有效的布局。 (它需要知道在哪里放置leftInfoSection水平)。 把那个约束连接到你的代码中,这样你就可以删除它。 除此之外,我有一个尾随约束GTE的垂直分频器+3。

3)最后的关键是考虑你需要处理的信息(在代码中,因为IB是有限的)。 我意识到,我知道我的部分上方的水平分隔线的中心,并且我的leftInfoSection部分的中心将是该水平条的中心减去水平条宽度的四分之一。 以下是左侧和右侧的最终代码:

 // 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时,它将保持断开其中一个或另一个,并对superview进行约束以定义宽度。 诀窍是暂时将不需要的约束留在原地,但将其优先级降低到999.然后,我可以创build子视图约束来定义宽度。

在斯坦福大学的ios 7讲座中考虑了这个问题的解决scheme。它的工作非常漂亮。在这里附上了解决scheme。 (这里sdfssfg …东西是label1和efsdfg ….东西是label2)

在这里输入图像说明

这工作相当好,但需要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]]; } 

在iOS 9之后,另一个select是使用Stack Views

你可能想引用这个

基于百分比的标记

基本上,它说,首先与一些不正确的边际,然后纠正与父母的看法。

与我的情况一起工作。