ios AutoLayout 以保持视图大小成比例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12840332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:41:57  来源:igfitidea点击:

AutoLayout to keep view sizes proportional

iosinterface-builderios6autolayoutnslayoutconstraint

提问by Simon Germain

I'm trying to achieve the following:

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

  • I have 2 views in my xib that need to stay 20 pixels off the edge (both sides and top)
  • The 2 views that need to resize aren't the same size
  • They have to be 20 pixels apart
  • Their width needs to stay relative to the width of the parent view
  • 我的 xib 中有 2 个视图需要在边缘(两侧和顶部)保持 20 像素
  • 需要调整大小的 2 个视图大小不同
  • 它们必须相距 20 像素
  • 它们的宽度需要保持相对于父视图的宽度

I read a tutorial about doing just that and it works but the problem with it is that it requires both views to have the same width and pin Widths equally, which I don't want.

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

Here's what I tried:

这是我尝试过的:

  • Add leading space constraint to left view to be 20 pixels
  • Add top space constraint to left view to be 20 pixels
  • Add top space constraint to right view to be 20 pixels
  • Add tailing space constraint to right view to be 20 pixels
  • Add horizontal spacing constraint to both views to be 20 pixels
  • 向左视图添加前导空间约束为 20 像素
  • 向左视图添加顶部空间约束为 20 像素
  • 将顶部空间约束添加到右视图为 20 像素
  • 向右视图添加拖尾空间约束为 20 像素
  • 为两个视图添加水平间距约束为 20 像素

The problem I'm running into is that the left view doesn't resize and the right view fills out the space to keep the 20 pixels horizontal space.

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

Is there a way I can get both views to resize proportionally to the space they should be filling?

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

Here are the screenshots of my layout and constraints:

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

xib LayoutConstraints definitions

xib 布局约束定义

Thanks!

谢谢!

EDIT

编辑

I get the following warning when I try to rotate my device:

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

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

采纳答案by Yatheesha B L

This can be resolved by adding one more dummy view(dummyView) with its constraints set to Fixed width, height and aligned to centerX of Superview.Then add left view and right view Horizontal spacing constraint to dummyView.

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

enter image description hereenter image description here

在此处输入图片说明在此处输入图片说明

回答by Benjamin

I'm probably late in coming up with a solution but this can actually be made very easilyin IB.

我可能迟迟没有提出解决方案,但这实际上可以在IB 中轻松实现。

First, add a UIViewand pin in to all four edges of the superview.

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

Then, Add your first subviewand position it accordingly (ig : x = 0, y = 0, height = fixed height, width = The width you would like relative to the UIViewwe pinned to all four edges).

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

Select both the UIViewand the first subviewand add an Equal Widthsconstraint. Of course, this will show you an error in positioning in the autolayout, but that's OK because this is not (yet) what you want.

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

Now comes the trick :select the Equal Widthsconstraint and edit the Multiplierto be the ratio you want (eg : 1:4 if you want the first subview to be 1/4 of the UIView). Repeat steps for the second subview and Tadaaaaaa !

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

enter image description here

在此处输入图片说明

回答by Ian L

I'm new to autolayout but came across your question and thought it would be a good challenge. (That's my caveat in case this isn't the ideal solution!)

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

You'll need to add the width constraints in code. I achieved this by firstly adding the two views in the NIB without width constraints. These are the constraints for the first (left) view:

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

enter image description here

在此处输入图片说明

These are the constraints I had for the second (right) view:

这些是我对第二个(右)视图的约束:

enter image description here

在此处输入图片说明

This leaves an extra constraint you don't want on the second view - leading space between superview and the second view as shown below:

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

enter image description here

在此处输入图片说明

You can't remove that constraint in IB as it would leave an ambiguous layout (as we don't have widths on the subviews). However you can remove it in code. Firstly, set up an outlet for it and connect it in IB:

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

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

Then, in your view controller's viewDidLoad, you can remove it using:

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

[self.view removeConstraint:self.view2superviewLeadingConstraint];

Finally, add the width constraints. The key here is the multiplier parameter to dicate what percentage you want the widths to be based on the superview width. Also note that you have to set the constant parameters to equal the leading/trailing totals set up in IB:

最后,添加宽度约束。这里的关键是 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];

回答by Rémy Virin

Just select the aspect ratio :

只需选择纵横比:

enter image description here

在此处输入图片说明

回答by JiBB

As others have mentioned, the key is setting a multiplier on the "Pin Widths Equally" constraint so that the views widths end up being a multiple of each other. XCode 5.1 should add the ability to set this in Interface Builder, but until then you've got another option besides setting it in code. If you create the "Pin Widths Equally" constraint, then go to the Identity Inspector in the Utilities Panel on the right, then look for "User Defined Runtime Attributes". Add a new attribute with key path "multiplier", type "number", and value equal to your desired ratio.

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

Multiplier set as a runtime attribute, as described above.

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

This won't be reflected in Interface Builder, but will apply when your view is used.

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

回答by Eugene Braginets

In Interface Builder drag the view with right button (just a bit to display black popup).
In popup menu select Aspect Ratio.

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

回答by Beninho85

It's now possible in XCode 6 with the aspect ratio property

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

回答by an0

  1. Remove the two width constraints in code, or lessen their priorities in IB, otherwise you are over-constrained.
  2. Add a constraint to describe the width ratio between the green view and blue view, in code:

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

回答by lxt

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 looksfrom 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 mustbe equal to 90 points exactly.

看起来从您发布您设置一些限制是明确的屏幕抓取-例如,你的左边绿色视图有一个约束,上面写着“宽度(90)”,这意味着宽度必须等于90点准确。

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

这可以通过多种方式修复 - 您可以删除视图上的那些显式宽度约束,或者您可以更改它们的优先级(默认情况下约束是“必需的”,但您可以将它们更改为可选)。