ios 如何在运行时更改标签约束?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19707229/
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
How to change label constraints during runtime?
提问by Centurion
I have a table view and a cell inside it. The cell contains three labels: header label and two labels below one to each other. Sometimes, I need to hide those two labels below if they do not contain data and change "Top space to container" of "Header label" to "Center Y to container". And of course revert the constraints back when two labels contain data. Here's a screenshot of simple demo project just for showing the idea:
我有一个表格视图和一个单元格。单元格包含三个标签:标题标签和两个彼此相对的标签。有时,如果它们不包含数据,我需要隐藏下面的这两个标签,并将“标题标签”的“顶部空间到容器”更改为“中心 Y 到容器”。当然,当两个标签包含数据时,恢复约束。这是一个简单的演示项目的屏幕截图,只是为了展示这个想法:
UPDATEMax MacLeod answer pointed to right direction. The trick is to push header label down when first and second labels are hidden. So we need to set bottom space to container view for first and second labels instead of creating top space to container view for header label. And hiding/unhiding should be done by having height outlets (height constraints for first and second label) and setting their constant values to zero (and setting back value when unhiding). I also uploaded the source code example to Github.
更新Max MacLeod 的回答指出了正确的方向。诀窍是在隐藏第一个和第二个标签时将标题标签向下推。因此,我们需要为第一个和第二个标签的容器视图设置底部空间,而不是为标题标签的容器视图创建顶部空间。隐藏/取消隐藏应该通过具有高度出口(第一个和第二个标签的高度限制)并将其常量值设置为零(并在取消隐藏时设置回值)来完成。我还将源代码示例上传到 Github。
回答by Max MacLeod
Select the header label, and one of the lower labels, and add a new vertical space constraint reflecting the gap between them. Next, remove the header label Top space to container constraint. Maybe you already have this (can't quite see from the screen grab). If you do, that's good.
选择标题标签和下方标签之一,并添加反映它们之间间隙的新垂直空间约束。接下来,删除标题标签 Top space to container 约束。也许你已经有了这个(不能从屏幕抓取中完全看到)。如果你这样做,那很好。
Now, create two height constraints for each lower label. IBOutlet
those to your class.
现在,为每个较低的标签创建两个高度约束。IBOutlet
那些给你的班级。
Then, hide those two lower labels whenever you need to by setting each height constraint's constant
to 0.f
.
然后,只要通过设置每个高度约束的需要隐藏这两个较低的标签constant
来0.f
。
That will render them invisible and lower the header label above so that it is now vertically centered Y in the container.
这将使它们不可见并降低上面的标题标签,以便它现在在容器中垂直居中 Y。
Will go through the steps once more (was too long for a comment!). Sequence matters with IB as first you must add a new constraint before you can delete the old one. Temporarily you will have one superfluous constraint. It's because IB won't allow ambiguity. So, first add the new vertical space constraint. That will define the Y position of the upper label. Then, remove the superfluous vertical space to container constraint from the upper label. Now that label will be Y positioned using the vertical space relative to the lower labels. Next, add the height constraints for each lower label and link to the class with an IBOutlet. One other thing, actually you will need the lower labels to be constrained to the container with a bottom space constraint. When their height is reduced to zero, they will disappear, and the upper label will move lower to assume the Y center position.
将再次执行这些步骤(评论太长了!)。序列对 IB 很重要,因为首先您必须添加新约束,然后才能删除旧约束。暂时你会有一个多余的约束。这是因为IB不允许歧义。因此,首先添加新的垂直空间约束。这将定义上标签的 Y 位置。然后,从上部标签中移除容器约束的多余垂直空间。现在该标签将使用相对于较低标签的垂直空间进行 Y 定位。接下来,为每个较低的标签添加高度约束,并使用 IBOutlet 链接到类。另一件事,实际上您需要将较低的标签约束到具有底部空间约束的容器。当它们的高度减小到零时,它们将消失,并且上部标签将向下移动以占据 Y 中心位置。
To revert, just set the constant
back to the original value.
要恢复,只需将constant
返回值设置为原始值。
This is a much better approach than adding/removing constraints, which is a heavyweight operation. Note that you may wish to add the two lower labels to a "container" view, so that they can be shown/hidden as one. Also, it would tidy the code as you really want the vertical space to be between your upper label, and both lower labels rather than just one.
这是一个比添加/删除约束更好的方法,这是一个重量级的操作。请注意,您可能希望将下面的两个标签添加到“容器”视图中,以便它们可以显示/隐藏为一个。此外,它会整理代码,因为您确实希望垂直空间位于上标签和下标签之间,而不仅仅是一个。
See also my answer AutoLayout with hidden UIViews?
另请参阅我的答案AutoLayout with hidden UIViews?
回答by Jorge Arimany
Put the labels you want to hide into a view, once everything has the correct layout constraints, add a height constraint to the container view, and connect the constraint into an IBOutlet
property.
将要隐藏的标签放入视图中,一旦所有内容都具有正确的布局约束,向容器视图添加高度约束,并将约束连接到IBOutlet
属性中。
Make sure that your properties are strong
确保您的属性是 strong
in code yo just have to set the constant to 0 and activate it, tho hide the content, or deactivate it to show the content.
This is better than messing up with the constant value an saving-restoring it.
Do not forget to call layoutIfNeeded
afterwards.
在代码中,您只需将常量设置为 0 并激活它,隐藏内容,或停用它以显示内容。这比弄乱常量值并保存恢复它要好。之后不要忘记打电话layoutIfNeeded
。
@property (strong, nonatomic) IBOutlet UIView *myContainer;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *myContainerHeight; //should be strong!!
-(void) showContainer
{
self.myContainerHeight.active = NO;
self.myContainer.hidden = NO;
[self.view layoutIfNeeded];
}
-(void) hideContainer
{
self.myContainerHeight.active = YES;
self.myContainerHeight.constant = 0.0f;
self.myContainer.hidden = YES;
[self.view layoutIfNeeded];
}
Once you have your setup you can test it in IntefaceBuilder by setting your constraint to 0 and then back to the original value. Don't forget to check other constraints priorities so when hidden there is no conflict at all. other way to test it is to put it to 0 and set the priority to 0, but, you should not forget to restore it to the highest priority again.
完成设置后,您可以在 IntefaceBuilder 中测试它,方法是将约束设置为 0,然后返回到原始值。不要忘记检查其他约束优先级,以便隐藏时根本没有冲突。另一种测试方法是将其设置为0并将优先级设置为0,但是,您不应忘记再次将其恢复为最高优先级。
回答by David H
I'm doing something very much like this myself. So add a width constraint to both labels. You are allowed to change the constant value while the constraint is applied - just keep a reference to it. In my case I have an array into which I put the constraints I plan to change.
我自己也在做类似的事情。因此,为两个标签添加宽度约束。您可以在应用约束时更改常量值 - 只需保留对它的引用。就我而言,我有一个数组,我将计划更改的约束放入其中。
When you want to hide the labels, change the c
value to 0 - you can do this in an animation block too. To show change the value.
当您想隐藏标签时,将c
值更改为 0 - 您也可以在动画块中执行此操作。显示更改值。
You could also make the width of the top space equal to the bottom space, so when the views hide or show you keep the "group" of items centered.
您还可以使顶部空间的宽度等于底部空间,因此当视图隐藏或显示时,您可以将项目的“组”保持居中。
Note that you can add or delete constraints too but its more costly for iOS to deal with.
请注意,您也可以添加或删除约束,但 iOS 的处理成本更高。
回答by Dumoko
Rarely you can fin smth easy to understand and some hands-on examples when it is up to Apple Documentation, but this is the exact case of the exception in the rule.
当涉及到 Apple 文档时,您很少能找到易于理解的内容和一些动手示例,但这是规则中例外的确切情况。
I personally found this document so easy to understand, and so clear. The best way to become an auto-layout guru in time :)
我个人觉得这个文档很容易理解,也很清晰。及时成为自动布局大师的最佳方式:)
Basically, runtime means "programmatically".
基本上,运行时意味着“以编程方式”。
So the answer to your question lies here:
所以你的问题的答案就在这里: