I am using autolayout in iOS to try and build a layout with fluid widths. The visual format for the constraint I am currently using is:
我在iOS中使用autolayout尝试构建具有流体宽度的布局。我目前使用的约束的可视格式是:
[self.scrollViewContainer addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-(>=32)-[viewToAdd(<=576)]-(>=32)-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(viewToAdd)
]];
That is to say: I want a minimum of 32px spacing on either side, and I want the viewToAdd
to have a maximum width of 576px. This works well except that I want the viewToAdd
to use up any available space while still meeting all the constraints. Currently I get the viewToAdd
only ever being as wide as its intrinsic content size, and the spacing growing as needed.
也就是说:我希望两边至少有32px的间距,我希望viewToAdd的最大宽度为576px。这很好用,除了我希望viewToAdd在满足所有约束的同时耗尽任何可用空间。目前,我只能看到viewToAdd与其内在内容大小一样宽,并且间距会根据需要增长。
Is there a way to specify that the viewToAdd
should be as large as possible?
有没有办法指定viewToAdd应该尽可能大?
2 个解决方案
#1
35
You're going to have to specify additional constraints on the view in order to get it to size the view to fill the remaining available space. Currently, you are setting the view minimums and maximums, but not setting any concrete constraints to give autolayout a more complete solution. In addition to the upper bound for the width, you need to give it 1. a starting point to solve the width for the view by either explicitly giving it a width at a lower priority, or 2. give the spacing on either side some more rigid constraints.
您将不得不在视图上指定其他约束,以使其调整视图大小以填充剩余的可用空间。目前,您正在设置视图最小值和最大值,但未设置任何具体约束以为autolayout提供更完整的解决方案。除了宽度的上限之外,你需要给它一个起点来解决视图的宽度,方法是明确地给它一个较低优先级的宽度,或者2.给两边的间距更多一些严格约束。
Based on what you've described, you need to constrain your view to give it some more substantial bindings to the superview on either side in order to let the system solve for the width. Since you would like to have the view size itself based on it's container's size, you will need to modify the spacing constraints (option 2 from above). In the above instance, you have specified only a minimum spacing, which would result in any of the following constraint solutions being found as valid by the autolayout engine for a 400pt superview:
根据您所描述的内容,您需要限制视图,以便为任何一方的superview提供更多实质性绑定,以便让系统解决宽度问题。由于您希望根据容器的大小来确定视图大小,因此您需要修改间距约束(上面的选项2)。在上面的例子中,您只指定了最小间距,这将导致以下任何约束解决方案被400lay superview的autolayout引擎视为有效:
|-32pt-[20pt]-------348pt-| <-- autolayout will probably choose this one
|-100pt----[20pt]---280pt-|
|-50pt--[20pt-]-----330pt-|
Which is probably not what you are wanting. Even more still, the width of the view can be anything between 0-576pt, which is also probably not what you're wanting. Since autolayout doesn't know what you want, it's simply using the intrinsicContentSize
of the view for concrete sizing constraints. Since you chose 32pt as the spacing, a first step would be to give the spacing constraints some more substantial instructions, namely, telling the system that the spacing should be 32pts between the edges of the view and the superview unless the width of the view is >576pts. You would do this like so in your VFL string:
这可能不是你想要的。更进一步,视图的宽度可以是0-576pt之间的任何值,这也可能不是你想要的。由于autolayout不知道你想要什么,它只是简单地使用视图的intrinsicContentSize来获得具体的大小限制。由于你选择32pt作为间距,第一步是给间距约束一些更实质的指令,即告诉系统视图边缘和超视图之间的间距应该是32pts,除非视图的宽度是> 576pts。你会在你的VFL字符串中这样做:
"H:|-(>=32,==32@900)-[viewToAdd(<=576)]-(>=32,==32@900)-|"
This says: "viewToAdd
should have a maximum width of 576pts and have padding between itself and it's superview of 32pts. If the size of the superview grows beyond the maximum width of viewToAdd
plus the initial padding of 64pts, the padding on either side should grow in order to continue to solve the constraint set."
这说:“viewToAdd的最大宽度应为576pts,并且在它自身之间有填充,它的超视距为32pts。如果超视图的大小超出viewToAdd的最大宽度加上64pts的初始填充,则任何一侧的填充都应该增长为了继续解决约束集。“
This results in the following constraints being correct for a 400pt superview:
这导致以下约束对于400pt superview是正确的:
|-32pt--[336pt]--32pt-|
If you would like for viewToAdd
to remain centered in it's superview when the view grows beyond the maximum, you will have to pass in the option NSLayoutFormatAlignAllCenterX
to the options
parameter in [NSLayoutConstraint -constraintsWithVisualFormat:]
. If you did not have the >=32
constraint set on the padding, or did not set a priority lower than 1000 ("required" constraint priority level) on your padding's ==32
constraint, then your superview would be unable to grow beyond 640pts.
如果您希望viewToAdd在视图超出最大值时保持其超级视图的居中,则必须将选项NSLayoutFormatAlignAllCenterX传递给[NSLayoutConstraint -constraintsWithVisualFormat:]中的options参数。如果您没有在填充上设置> = 32约束,或者没有在padding的== 32约束上设置低于1000(“必需”约束优先级别)的优先级,那么您的超级视图将无法超过640pts 。
#2
1
Not sure if this exactly answers the question, but for the ones using Storyboard: I found that you can add a width-constraint and constraints for both the distance to the left and right side of the parent view for example. If you then change the width-constraint to '<=' instead of '=' and set the priority of the distance constraints (both leading and trailing) to 750, the view will max out to the max width, respecting the distance-constraints if the view is too small.
不确定这是否完全回答了问题,但对于使用Storyboard的问题:我发现你可以为父视图的左侧和右侧的距离添加宽度约束和约束。如果然后将width-constraint更改为'<='而不是'='并将距离约束(前导和尾随)的优先级设置为750,则视图将最大化到最大宽度,并遵循距离约束如果视图太小。
#1
35
You're going to have to specify additional constraints on the view in order to get it to size the view to fill the remaining available space. Currently, you are setting the view minimums and maximums, but not setting any concrete constraints to give autolayout a more complete solution. In addition to the upper bound for the width, you need to give it 1. a starting point to solve the width for the view by either explicitly giving it a width at a lower priority, or 2. give the spacing on either side some more rigid constraints.
您将不得不在视图上指定其他约束,以使其调整视图大小以填充剩余的可用空间。目前,您正在设置视图最小值和最大值,但未设置任何具体约束以为autolayout提供更完整的解决方案。除了宽度的上限之外,你需要给它一个起点来解决视图的宽度,方法是明确地给它一个较低优先级的宽度,或者2.给两边的间距更多一些严格约束。
Based on what you've described, you need to constrain your view to give it some more substantial bindings to the superview on either side in order to let the system solve for the width. Since you would like to have the view size itself based on it's container's size, you will need to modify the spacing constraints (option 2 from above). In the above instance, you have specified only a minimum spacing, which would result in any of the following constraint solutions being found as valid by the autolayout engine for a 400pt superview:
根据您所描述的内容,您需要限制视图,以便为任何一方的superview提供更多实质性绑定,以便让系统解决宽度问题。由于您希望根据容器的大小来确定视图大小,因此您需要修改间距约束(上面的选项2)。在上面的例子中,您只指定了最小间距,这将导致以下任何约束解决方案被400lay superview的autolayout引擎视为有效:
|-32pt-[20pt]-------348pt-| <-- autolayout will probably choose this one
|-100pt----[20pt]---280pt-|
|-50pt--[20pt-]-----330pt-|
Which is probably not what you are wanting. Even more still, the width of the view can be anything between 0-576pt, which is also probably not what you're wanting. Since autolayout doesn't know what you want, it's simply using the intrinsicContentSize
of the view for concrete sizing constraints. Since you chose 32pt as the spacing, a first step would be to give the spacing constraints some more substantial instructions, namely, telling the system that the spacing should be 32pts between the edges of the view and the superview unless the width of the view is >576pts. You would do this like so in your VFL string:
这可能不是你想要的。更进一步,视图的宽度可以是0-576pt之间的任何值,这也可能不是你想要的。由于autolayout不知道你想要什么,它只是简单地使用视图的intrinsicContentSize来获得具体的大小限制。由于你选择32pt作为间距,第一步是给间距约束一些更实质的指令,即告诉系统视图边缘和超视图之间的间距应该是32pts,除非视图的宽度是> 576pts。你会在你的VFL字符串中这样做:
"H:|-(>=32,==32@900)-[viewToAdd(<=576)]-(>=32,==32@900)-|"
This says: "viewToAdd
should have a maximum width of 576pts and have padding between itself and it's superview of 32pts. If the size of the superview grows beyond the maximum width of viewToAdd
plus the initial padding of 64pts, the padding on either side should grow in order to continue to solve the constraint set."
这说:“viewToAdd的最大宽度应为576pts,并且在它自身之间有填充,它的超视距为32pts。如果超视图的大小超出viewToAdd的最大宽度加上64pts的初始填充,则任何一侧的填充都应该增长为了继续解决约束集。“
This results in the following constraints being correct for a 400pt superview:
这导致以下约束对于400pt superview是正确的:
|-32pt--[336pt]--32pt-|
If you would like for viewToAdd
to remain centered in it's superview when the view grows beyond the maximum, you will have to pass in the option NSLayoutFormatAlignAllCenterX
to the options
parameter in [NSLayoutConstraint -constraintsWithVisualFormat:]
. If you did not have the >=32
constraint set on the padding, or did not set a priority lower than 1000 ("required" constraint priority level) on your padding's ==32
constraint, then your superview would be unable to grow beyond 640pts.
如果您希望viewToAdd在视图超出最大值时保持其超级视图的居中,则必须将选项NSLayoutFormatAlignAllCenterX传递给[NSLayoutConstraint -constraintsWithVisualFormat:]中的options参数。如果您没有在填充上设置> = 32约束,或者没有在padding的== 32约束上设置低于1000(“必需”约束优先级别)的优先级,那么您的超级视图将无法超过640pts 。
#2
1
Not sure if this exactly answers the question, but for the ones using Storyboard: I found that you can add a width-constraint and constraints for both the distance to the left and right side of the parent view for example. If you then change the width-constraint to '<=' instead of '=' and set the priority of the distance constraints (both leading and trailing) to 750, the view will max out to the max width, respecting the distance-constraints if the view is too small.
不确定这是否完全回答了问题,但对于使用Storyboard的问题:我发现你可以为父视图的左侧和右侧的距离添加宽度约束和约束。如果然后将width-constraint更改为'<='而不是'='并将距离约束(前导和尾随)的优先级设置为750,则视图将最大化到最大宽度,并遵循距离约束如果视图太小。