以编程方式创建布局约束 [英] Creating layout constraints programmatically

查看:28
本文介绍了以编程方式创建布局约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道很多人已经问过很多关于这个的问题,但即使有答案我也无法解决.

I know that a lot people already asked tons of questions about this, but even with the answers I can't make it work.

当我处理故事板的约束时,这很容易,但在代码中我很难.例如,我尝试让视图停留在右侧并根据屏幕方向具有屏幕高度.这是我的代码:

When I'm dealing with constraints on storyboard, it's easy but in code I have a hard time. I try, for example, to have a view that stays on the right side and has the height of the screen according the screen orientation. This is my code:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

它不满足一些约束.我看不出有什么问题.另外,为什么我不能使用像 self.myView 这样的属性而不是像 myView 这样的局部变量?

It doesn't satisfy some constraints. I don't see what is wrong. Also, why can't I use a property like self.myView instead of a local variable like myView?

推荐答案

在代码中使用自动布局时,设置框架没有任何作用.因此,您在上面的视图中指定宽度为 200 的事实在您对其设置约束时没有任何意义.为了使视图的约束集明确无误,它需要四件事:任何给定状态的 x 位置、y 位置、宽度和高度.

When using Auto Layout in code, setting the frame does nothing. So the fact that you specified a width of 200 on the view above, doesn't mean anything when you set constraints on it. In order for a view's constraint set to be unambiguous, it needs four things: an x-position, a y-position, a width, and a height for any given state.

目前在上面的代码中,你只有两个(高度,相对于父视图,y 位置,相对于父视图).除此之外,您还有两个必需的约束可能会发生冲突,具体取决于视图的超视图约束的设置方式.如果 superview 有一个必需的约束,指定它的高度小于 748,你会得到一个不可满足的约束"异常.

Currently in the code above, you only have two (height, relative to the superview, and y-position, relative to the superview). In addition to this, you have two required constraints that could conflict depending on how the view's superview's constraints are setup. If the superview were to have a required constraint that specifies it's height be some value less than 748, you will get an "unsatisfiable constraints" exception.

在设置约束之前设置视图的宽度这一事实毫无意义.它甚至不会考虑旧框架,而是根据它为这些视图指定的所有约束来计算新框架.在代码中处理自动布局时,我通常只使用 initWithFrame:CGRectZero 或简单地使用 init 创建一个新视图.

The fact that you've set the width of the view before setting constraints means nothing. It will not even take the old frame into account and will calculate a new frame based on all of the constraints that it has specified for those views. When dealing with autolayout in code, I typically just create a new view using initWithFrame:CGRectZero or simply init.

要创建您在问题中口头描述的布局所需的约束集,您需要添加一些水平约束来限制宽度和 x 位置,以便提供完全指定的布局:

To create the constraint set required for the layout you verbally described in your question, you would need to add some horizontal constraints to bound the width and x-position in order to give a fully-specified layout:

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:[myView(==200)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

从垂直约束开始,口头描述此布局如下:

Verbally describing this layout reads as follows starting with the vertical constraint:

myView 将使用顶部和底部填充填充其父视图的高度等于标准空间.myView 的超级视图具有最小高度748 分.myView 的宽度为 200pts 并且右填充等于与其父视图相对的标准空间.

myView will fill its superview's height with a top and bottom padding equal to the standard space. myView's superview has a minimum height of 748pts. myView's width is 200pts and has a right padding equal to the standard space against its superview.

如果您只是希望视图填充整个超级视图的高度而不限制超级视图的高度,那么您只需省略视觉格式文本中的 (>=748) 参数.如果您认为需要 (>=748) 参数来为其指定高度 - 在这种情况下您不需要:使用栏 (| 将视图固定到超级视图的边缘)) 或带有空格的栏 (|-, -|) 语法,您给视图一个 y 位置(将视图固定在单边上)),以及一个带有高度的 y 位置(将视图固定在两个边缘上),从而满足您为视图设置的约束.

If you would simply like the view to fill the entire superview's height without constraining the superview's height, then you would just omit the (>=748) parameter in the visual format text. If you think that the (>=748) parameter is required to give it a height - you don't in this instance: pinning the view to the superview's edges using the bar (|) or bar with space (|-, -|) syntax, you are giving your view a y-position (pinning the view on a single-edge), and a y-position with height (pinning the view on both edges), thus satisfying your constraint set for the view.

关于你的第二个问题:

使用 NSDictionaryOfVariableBindings(self.myView)(如果您为 myView 设置了属性)并将其输入您的 VFL 以在您的 VFL 文本中使用 self.myView,当自动布局尝试解析您的 VFL 文本时,您可能会遇到异常.它与字典键中的点符号和尝试使用 valueForKeyPath: 的系统有关.请参阅此处了解类似的问答.

Using NSDictionaryOfVariableBindings(self.myView) (if you had an property setup for myView) and feeding that into your VFL to use self.myView in your VFL text, you will probably get an exception when autolayout tries to parse your VFL text. It has to do with the dot notation in dictionary keys and the system trying to use valueForKeyPath:. See here for a similar question and answer.

这篇关于以编程方式创建布局约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆