考虑一个包含三个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)并从约束中取出填充。我可能会走这条路,只是希望有一种方法来定义在约束定义中折叠这个填充。
答案 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)