对于iOS布局限制,当高度为0时,是否可以折叠标签之间的填充?

时间:2013-10-03 18:30:23

标签: ios autolayout nslayoutconstraint

考虑一个包含三个UILabel的视图,其垂直约束定义如下:

[self.view
 addConstraints:[NSLayoutConstraint
                 constraintsWithVisualFormat:@"V:[label1]-2-[label2]-2-[label3]"
                 options:0
                 metrics:nil
                 views:views]];

这将生成一个布局,标签垂直堆叠,每个标签之间有2px填充。

在我的应用程序中,有时一个或多个标签上显示的文本为nil(或空白),这意味着标签框架以高度== 0结束。在这种情况下,我希望在0高度之间的2px填充标签要折叠。

当所有标签都有文本值时,我希望布局为:

label1文字
[2px的]
label2文本
[2px的]
label3文本

label2的文本值为零时,我希望布局为:

label1文字
[2px的]
label3文本

在后一种情况下,标签2实际上仍然存在但是高度为0且其2px填充已经折叠。

问题:这可能吗?我如何定义约束来实现这一目标?

修改

我意识到可以在UILabel的子类中实现填充(edge inset)并从约束中取出填充。我可能会走这条路,只是希望有一种方法来定义在约束定义中折叠这个填充。

3 个答案:

答案 0 :(得分:0)

是的,有一种方法可以做到这一点,你应该通过修改约束而不是弄乱UILabel子类来解决这个问题。但是,使用VFL当你正在做的事情有点棘手,因为你需要做的是保持对每个标签之间的各个约束的引用,并且VFL返回一系列约束(所以你不知道哪个是哪个。

因此,假设您没有使用VFL,您将需要单独创建每对标签之间的约束并将其存储在ivar或属性中:

NSLayoutConstraint *label1To2Constraint = [NSLayoutConstraint constraintWith...];
NSLayoutConstraint *label2To3Constraint = [NSLayoutConstraint constraintWith...];

如果您明确添加约束以在标签上设置固定高度(您正在使用的VFL代码不执行此操作),那么如果标签中没有文本,它会缩小到零高度。所以现在你需要做的就是更新标签的文本后,检查标签是否有文本,并根据需要更新每对之间约束的constant属性:

BOOL hasLabel1Text = label1.text.length > 0;
BOOL hasLabel2Text = label2.text.length > 0;
BOOL hasLabel3Text = label3.text.length > 0;
label1To2Constraint.constant = (hasLabel1Text && hasLabel2Text) ? 2.0f : 0.0f;
label2To3Constraint.constant = (hasLabel2Text && hasLabel3Text) ? 2.0f : 0.0f;

更改现有约束的constant可以(并且应该)完成,无需删除并重新添加约束。这非常有效。 (删除和重新添加约束对内部Auto Layout引擎更加重要,应尽可能避免使用。)

为了给你省点痛苦,我想指出你所创造的UIView+AutoLayout category。我保证使用最薄的第三方代码可以大大改善您使用自动布局的体验。您将看到创建此场景所需的约束非常容易。

答案 1 :(得分:0)

当您在标签中显示的值发生变化时,您可以重新定义约束。

如果这是一个具有三个字符串属性的视图子类,则在每个属性的setter中,您可以调用setNeedsUpdateConstraints

然后,在updateConstraints实现中,删除先前创建的约束(如果需要,可以存储在属性中,因为VFL方法返回一个数组)并重新生成相应的约束。

如果您在处理布局的视图控制器中,则有一种用于更新视图控制器视图上的约束的类似方法:updateViewConstraints

答案 2 :(得分:0)