AutoLayout可保持视图大小成比例

时间:2012-10-11 13:10:40

标签: ios interface-builder ios6 autolayout nslayoutconstraint

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

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

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

这是我试过的:

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

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

有没有办法可以让两个视图按照他们应该填充的空间按比例调整大小?

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

xib Layout Constraints definitions

谢谢!

修改

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

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)]>

9 个答案:

答案 0 :(得分:75)

我可能会提出一个解决方案,但实际上这可以在 IB 非常容易

首先,添加 UIView 并将其固定到超级视图的所有四个边缘。

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

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

现在就来了:选择 Equal Widths 约束并编辑 Multiplier 以达到您想要的比例(例如:1:4)如果你想第一个子视图是UIView的1/4)。 重复第二个子视图和Tadaaaaaa的步骤!

enter image description here

答案 1 :(得分:10)

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

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

enter image description here

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

enter image description here

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

enter image description here

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

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

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

[self.view removeConstraint:self.view2superviewLeadingConstraint];

最后,添加宽度约束。这里的关键是乘数参数,用于指定宽度基于超视图宽度的百分比。另请注意,您必须将常量参数设置为等于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];

答案 2 :(得分:10)

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

enter image description here enter image description here

答案 3 :(得分:9)

只需选择宽高比:

enter image description here

答案 4 :(得分:6)

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

Multiplier set as a runtime attribute, as described above.

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

答案 5 :(得分: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];
    

答案 6 :(得分:1)

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

答案 7 :(得分:1)

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

答案 8 :(得分:0)

我不确定你对自动布局有多熟悉,如果这是你已经知道的东西,请道歉:

使用自动布局时,可以为同一属性分配多个约束。在某些情况下,这些约束可能相互矛盾。这就是导致你看到警告的原因。

从您发布的屏幕抓取中看起来您已将几个约束设置为显式 - 例如,左侧的绿色视图具有“宽度(90)”的约束,这意味着宽度必须完全等于90点。

仅从屏幕截图中不清楚你的其他约束被映射到什么,但这里可能发生的是这些显式约束导致问题 - 你有自动调整约束,说视图应该扩展或收缩以适应它们的可用区域,但那些相同的视图具有要求它们具有精确宽度的约束。

这可以通过多种方式修复 - 您可以删除视图上的显式宽度约束,也可以更改其优先级(默认约束是'required',但您可以将它们更改为可选)。