如何在运行时更改标签约束?

19
我有一个表格视图和其中的一个单元格。该单元格包含三个标签:标题标签和下方的两个标签,一个在另一个下方。有时,如果两个标签中没有数据,我需要隐藏它们并将“头部标签”的“顶部间距容器”更改为“垂直居中到容器”。当两个标签包含数据时,当然要恢复约束。这是一个简单的演示项目截图,仅用于展示想法:
enter image description here 更新 Max MacLeod 的答案指向了正确的方向。诀窍是当第一个和第二个标签隐藏时将标题标签向下推。因此,我们需要为第一个和第二个标签设置底部空间到容器视图,而不是为标题标签创建顶部空间到容器视图。通过具有高度线路(第一个和第二个标签的高度约束)并将其常量值设置为零(并在取消隐藏时设置回值)来进行隐藏/取消隐藏。我还上传了Github上的源代码示例
4个回答

34
选择标题标签和其中一个较低的标签,添加一个新的垂直空隙约束来反映它们之间的间隔。接下来,删除标题标签上方到容器的空格约束。如果您已经有这个(从屏幕截图中看不太清楚),那就很好。
现在,为每个较低的标签创建两个高度约束。将其连接到你的类中的 IBOutlet。
然后,每当您需要时通过将每个高度约束的 constant 设置为 0.f 来隐藏这两个较低的标签。
这将使它们变得看不见,并将上面的标题标签下移,使其在容器中现在处于垂直居中位置。
再次重复一遍步骤(对于评论来说太长了!)。在 IB 中顺序很重要,因为首先必须添加新约束,然后才能删除旧约束。临时会有一个多余的约束,这是因为 IB 不允许歧义。所以,首先添加新的垂直空隙约束。这将定义上标签的 Y 位置。然后,从上标签中删除多余的垂直空间到容器的约束。现在,该标签将使用相对于较低标签的垂直空间定位。接下来,添加每个较低标签的高度约束,并使用 IBOutlet 将其链接到类。还有一件事,实际上你需要将较低的标签约束到容器的底部,以便它们的高度减少到零时就会消失,而上标签将向下移动以占据 Y 中心位置。
要恢复原状,只需将 constant 设置回原始值即可。
这比添加/删除约束更好,因为后者是一个繁重的操作。请注意,您可能希望将两个较低标签添加到“容器”视图中,以便它们可以作为一个显示/隐藏。此外,它会整理代码,因为您确实希望垂直空格在您的上标签和两个较低标签之间,而不仅仅是一个。还可以参考我的回答 AutoLayout with hidden UIViews?

你说的“添加一个新的约束条件来使标题标签有一个垂直间隙”是什么意思?它应该是什么类型的约束条件?我已经通过垂直空间约束将较低的标签与标题标签固定在一起了。 - Centurion
如果我删除“顶部空间到容器”的约束,则 IB 会显示“需要 Y 位置的约束”错误。 - Centurion
是的,首先你需要给它一个新的约束,然后再添加那个现在多余的旧约束。IB不会允许有歧义。 - Max MacLeod
抱歉,我不理解你的评论。顺序很重要吗?我的意思是,我应该先从这些标签中删除所有现有的约束条件,然后将低标签与引脚头连接,然后再为低标签添加高度,这样IB就不会抱怨缺少垂直Y约束了吗? - Centurion
已经添加了更多细节。 - Max MacLeod

8
将您想要隐藏的标签放入一个视图中,一旦所有东西都有正确的布局约束,将一个高度约束添加到容器视图中,并将约束连接到一个IBOutlet属性中。
确保您的属性是strong
在代码中,你只需要将常量设置为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];
}

一旦您设置好了环境,您可以在 InterfaceBuilder 中测试它,方法是将约束条件设置为 0,然后再设置回原始值。不要忘记检查其他约束条件的优先级,以便在隐藏时完全没有冲突。另一种测试方法是将其设置为 0,并将优先级设置为 0,但是,您不应忘记将其恢复到最高优先级。


很棒的答案...我知道我们可以为约束保留一个插座,还有一个占位符约束..但现在知道我们可以激活这些约束。 - MANCHIKANTI KRISHNAKISHORE

0

我自己也在做类似的事情。所以给两个标签添加宽度约束。你可以在应用约束时更改常量值 - 只需保留对它的引用即可。在我的情况下,我有一个数组,我将要更改的约束放入其中。

当您想要隐藏标签时,请将 c 值更改为0 - 您也可以在动画块中执行此操作。要显示更改该值。

您还可以使顶部空间的宽度等于底部空间的宽度,这样当视图隐藏或显示时,您可以保持“组”中的项目居中。

请注意,您也可以添加或删除约束,但这会增加iOS的处理成本。


-3

当涉及到苹果文档时,很少能找到易于理解和实用的示例,但这正是规则中的例外。

我个人发现这份文档非常易于理解,而且清晰明了。这是成为自动布局专家的最佳途径 :)

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutinCode/AutoLayoutinCode.html

基本上,运行时意味着“以编程方式”。

因此,你的问题的答案就在这里:

https://dev59.com/3GjWa4cB1Zd3GeqPut3K#12623006


苹果链接已经失效,请考虑更新。 - Julian Osorio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接