使用 iOS 布局约束,当高度为 0 时,是不是可以折叠标签之间的填充?

Posted

技术标签:

【中文标题】使用 iOS 布局约束,当高度为 0 时,是不是可以折叠标签之间的填充?【英文标题】:With iOS layout contraints is it possible to collapse padding between labels when height is 0?使用 iOS 布局约束,当高度为 0 时,是否可以折叠标签之间的填充? 【发布时间】:2013-10-03 18:30:23 【问题描述】:

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

[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 的子类中实现填充(边缘插入)并将填充排除在约束之外。我可能会走那条路,只是希望有一种方法可以在约束定义中定义折叠此填充。

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

【参考方案2】:

是的,有一种方法可以做到这一点,您应该通过修改约束来解决这个问题,而不是弄乱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。我保证它将使用尽可能薄的第三方代码层显着改善您的自动布局体验。您会发现创建此场景所需的约束非常容易。

【讨论】:

【参考方案3】:

这对这类问题很有效: https://github.com/depth42/AutolayoutExtensions

【讨论】:

以上是关于使用 iOS 布局约束,当高度为 0 时,是不是可以折叠标签之间的填充?的主要内容,如果未能解决你的问题,请参考以下文章

当孩子的高度是 wrap_content 时,约束布局正在占用全宽

当我们使用不同尺寸和类型的屏幕时,如何在 iOS 中设置 UI 控件的宽度和高度约束?

在自动布局的情况下,IOS scrollview 模糊的可滚动内容高度

iOS 视图高度和自动布局

为约束布局内的布局设置最小百分比高度

使用自动布局为今天的 iOS8 扩展设置固定高度