49

我正在努力实现以下目标:

  • 我的 xib 中有 2 个视图需要保持 20 像素的边缘(两侧和顶部)
  • 需要调整大小的 2 个视图大小不同
  • 它们必须相距 20 像素
  • 它们的宽度需要保持相对于父视图的宽度

我阅读了一个关于这样做的教程并且它有效,但它的问题是它要求两个视图具有相同的宽度和 pin Widths equally,这是我不想要的。

这是我尝试过的:

  • 向左视图添加前导空间约束为 20 像素
  • 向左视图添加顶部空间约束为 20 像素
  • 将顶部空间约束添加到右视图为 20 像素
  • 为右视图添加拖尾空间约束为 20 像素
  • 向两个视图添加水平间距约束为 20 像素

我遇到的问题是左视图没有调整大小,而右视图填充了空间以保持 20 像素的水平空间。

有没有办法让两个视图按比例调整它们应该填充的空间?

这是我的布局和约束的屏幕截图:

xib 布局约束定义

谢谢!

编辑

尝试旋转设备时收到以下警告:

2012-10-11 08:59:00.435 AutolayoutTest[35672:c07] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want.
    Try this: (1) look at each constraint and try to figure out which you don't expect;
    (2) find the code that added the unwanted constraint or constraints and fix it. (Note:  
    If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x8a6b2b0 H:[UIView:0x8a6b1d0(170)]>",
    "<NSLayoutConstraint:0x8a68ad0 H:[UIView:0x8a69430(90)]>",
    "<NSLayoutConstraint:0x8a6ba40 H:[UIView:0x8a69430]-(20)-[UIView:0x8a6b1d0]>",
    "<NSLayoutConstraint:0x8a6ba00 H:[UIView:0x8a6b1d0]-(20)-|   (Names: '|':UIView:0x8a6b7e0 )>",
    "<NSLayoutConstraint:0x8a6b940 H:|-(20)-[UIView:0x8a69430]   (Names: '|':UIView:0x8a6b7e0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x7199aa0 h=--& v=--& V:[UIView:0x8a6b7e0(568)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x8a6b2b0 H:[UIView:0x8a6b1d0(170)]>
4

9 回答 9

76

我可能迟到了一个解决方案,但这实际上可以在IB中很容易地完成。

首先,添加一个UIView并固定到 superview 的所有四个边缘。

然后,添加您的第一个子视图并相应地定位它(例如:x = 0,y = 0,高度 = 固定高度,宽度 = 您希望相对于我们固定到所有四个边缘的UIView的宽度)。

选择UIView第一个子视图并添加一个等宽约束。当然,这会在自动布局中向您显示定位错误,但这没关系,因为这(还)不是您想要的。

现在技巧来了:选择Equal Widths约束并将乘数编辑为您想要的比率(例如:如果您希望第一个子视图为 UIView 的 1/4,则为 1:4)。对第二个子视图和 Tadaaaaaa 重复步骤!

在此处输入图像描述

于 2014-10-15T12:44:13.113 回答
10

我是自动布局的新手,但遇到了您的问题,并认为这将是一个很好的挑战。(这是我的警告,以防这不是理想的解决方案!)

您需要在代码中添加宽度约束。我通过首先在没有宽度限制的 NIB 中添加两个视图来实现这一点。这些是第一个(左)视图的约束:

在此处输入图像描述

这些是我对第二个(右)视图的限制:

在此处输入图像描述

这会在第二个视图上留下您不想要的额外约束 - 超级视图和第二个视图之间的前导空间,如下所示:

在此处输入图像描述

您不能在 IB 中删除该约束,因为它会留下不明确的布局(因为我们在子视图上没有宽度)。但是,您可以在代码中将其删除。首先,为其设置一个出口并在IB中连接它:

@property (nonatomic, strong) IBOutlet NSLayoutConstraint *view2superviewLeadingConstraint;

然后,在您的视图控制器中viewDidLoad,您可以使用以下方法将其删除:

[self.view removeConstraint:self.view2superviewLeadingConstraint];

最后,添加宽度约束。这里的关键是 multiplier 参数,用于指示您希望宽度基于超级视图宽度的百分比。另请注意,您必须将常量参数设置为等于 IB 中设置的前导/尾随总计:

NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.3 constant:-20];
[self.view addConstraint:constraint1];

NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.view2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.7 constant:-40];
[self.view addConstraint:constraint2];
于 2012-10-24T11:58:03.727 回答
10

这可以通过添加一个虚拟视图(dummyView)来解决,其约束设置为固定宽度、高度并与 Superview 的 centerX 对齐。然后将左视图和右视图水平间距约束添加到dummyView

在此处输入图像描述 在此处输入图像描述

于 2014-06-18T07:36:43.977 回答
9

只需选择纵横比:

在此处输入图像描述

于 2014-10-23T13:38:56.323 回答
6

正如其他人所提到的,关键是在“Pin Widths Equally”约束上设置一个乘数,以便视图宽度最终成为彼此的倍数。XCode 5.1 应该添加在 Interface Builder 中设置它的功能,但在那之前,除了在代码中设置它之外,您还有另一个选择。如果您创建“Pin Widths Equally”约束,然后转到右侧 Utilities Panel 中的 Identity Inspector,然后查找“User Defined Runtime Attributes”。添加一个新属性,其键路径为“multiplier”,键入“number”,值等于您想要的比率。

如上所述,乘数设置为运行时属性。

这不会反映在 Interface Builder 中,但会在使用您的视图时应用。

于 2014-03-01T11:14:21.330 回答
1
  1. 去掉代码中的两个宽度约束,或者在 IB 中减少它们的优先级,否则你就被过度约束了。
  2. 添加一个约束来描述绿色视图和蓝色视图之间的宽度比,在代码中:

    // Assuming the ratio you want is green_view_width : blue_view_width = 1 : 2
    NSLayoutConstraint *c = [NSLayoutConstraint constraintWithItem:greenView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeWidth multiplier:0.5f constant:0.f];
    [commonSuperview addConstraint:c];
    
于 2013-04-19T21:48:01.233 回答
1

现在可以在 XCode 6 中使用宽高比属性

于 2014-10-15T15:52:16.660 回答
1

在 Interface Builder 中,使用右键拖动视图(稍微显示黑色弹出窗口)。
在弹出菜单中选择Aspect Ratio.

于 2014-07-01T14:12:05.200 回答
0

I'm not sure how familiar you are with auto-layout, so apologies if this is stuff you already know:

When using auto-layout it's possible to assign several constraints to the same property. Under certain circumstances these constraints can contradict each other. This is what's causing the warning you're seeing.

It looks from the screen-grab you posted that you've set several constraints to be explicit - for example, your green view on the left has a constraint that says "Width (90)", which means the width must be equal to 90 points exactly.

It's unclear from the screenshot alone what your other constraints are mapped to, but what's probably happening here is these explicit constraints are causing problems - you have autoresizing constraints that say the views should expand or contract to fit their available area, but those same views have constraints that require them to be an exact width.

This can be fixed in a number of ways - you can either remove those explicit width constraints on your views, or you can change their priority (by default constraints are 'required', but you can change them to be optional).

于 2012-10-11T14:19:35.730 回答