使用 AutoLayout 在 UITableViewCell 中垂直居中多个 UILabel?

Posted

技术标签:

【中文标题】使用 AutoLayout 在 UITableViewCell 中垂直居中多个 UILabel?【英文标题】:Centering multiple UILabels vertically in a UITableViewCell using AutoLayout? 【发布时间】:2014-01-13 14:47:46 【问题描述】:

我开始实现 AutoLayout,我正在尝试拼凑如何正确连接我的自定义 UITableViewCell 类之一。它通常有两个UILabel 对象,一个在另一个之上,很像标准的字幕类。我希望这两个标签在单元格中居中,无论单元格的高度如何,两者之间有一个给定的填充。

我假设我可以通过添加两个标签的高度,添加填充,然后从单元格的高度中减去它,然后除以 2 来做到这一点。但是,我很好奇这在语义上是否正确,因为我会将它们限制在单元格的顶部和底部,而不是彼此之间。我是不是在这里漏了个把戏?

其次,有时还会在其中堆叠第三个标签,因此三个标签彼此重叠。在那种情况下,我需要两组填充等,但问题变得更加相关:我不应该将它们相互限制,而不是限制在单元格的顶部和底部吗?

所以,问题更多是语义问题:如果我想在父视图内垂直约束多个元素,有没有比我上面建议的方法更聪明的方法来做到这一点?

(我目前完全在代码中实现 AutoLayout(使用 Masonry),因为这个单元格没有 XIB 并且不在情节提要中)。

【问题讨论】:

如果您在此处绘制 UI 并显示它会很棒,因此我们可以提供更多帮助 【参考方案1】:

正确的方法是使用容器视图,它从其子视图中获取高度。然后将容器视图固定到单元格的中心 - 您不会有任何约束将容器链接到单元格的顶部和底部边缘。

在容器内,垂直约束为|[label1]-[label2]|,这将使容器成为两个标签加上空格的高度,容器视图的中心将位于两个标签之间。

如果添加三个标签,则为|[label1]-[label2]-[label3]|,容器的中心将位于中间标签的中心。

在每种情况下,容器的中心都将位于单元格的中心,您无需进行任何计算。

【讨论】:

我不太明白这有什么帮助。我仍在将标签绑在某物的顶部和底部,并允许调整它们之间的距离。我不希望这样,我希望标签之间的间距保持不变,并调整顶部上方和底部下方的间距。 好的,我已经扩展了一点,希望对您有所帮助。 一点。这是一个奇怪的世界,但经过几次阅读后,这是有道理的:)非常感谢! 在糟糕的 Xcode 上以非常直观的方式做事。感谢 Apple 提高了精神错乱级别。【参考方案2】:

使用 Interface Builder,我可以使用以下步骤将多个 UIView 垂直居中。我的用例是我希望这些多个 UIView 尽可能地表现得像一个组,但我不想引入任何进一步的视图来实现这一点。

首先,我使用底部的按钮选择我认为是我的默认外形尺寸(外形尺寸为 3.5 英寸或 4 英寸视网膜)。然后,我通过一次拖动一个按钮将按钮定位在视图的中心,并使用带有蓝色准则的自动捕捉来帮助解决此问题。

一旦按钮就位,我一次选择一个以应用它们的约束。单击一个按钮,然后从 Interface Builder 右下角的浮动按钮中选择 Align Constraints 菜单(我看到一组 4 个,而 Align 是左侧的一个,在外形尺寸按钮)。

在此菜单中,选中 Vertical Center In Container 复选框,然后单击以打开该值旁边的下拉菜单,该值可能为 0。从该列表中,选择 使用当前画布价值。然后,点击 Add Constraints 按钮(可能标记为 Add 1 Constraint)。

当您这样做时,如果您看到 容器中的垂直中心 旁边的值设置为 Y 偏移值,您可能会知道它正在工作,您可能会通过回看您的UIViews 的排列。

如果您不想使用 Interface Builder,我们深表歉意,但我自己在实现这一点时遇到了麻烦,想提一下这些步骤。您始终可以一次性使用 IB,并以编程方式在测试中注销约束,然后将它们应用到您的纯代码解决方案中。

【讨论】:

tl;dr:使用自动布局将每个项目垂直居中,并为约束添加 Y 偏移量。 感谢这个 Cloov。正在苦苦挣扎,完全忘记了“使用当前画布大小”。 太难理解了,能否提供项目源码。【参考方案3】:

假设您有label1label2label3cell

// Center the labels
[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeCenterX
                            multiplier:1.0 constant:0]
[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeCenterX
                            multiplier:1.0 constant:0]
[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeCenterX
                            multiplier:1.0 constant:0]

// Vertical alignment/spacing of 8 between each label
[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                toItem:cell.contentView attribute:NSLayoutAttributeTop
                            multiplier:1.0 constant:0]
[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                toItem:label1 attribute:NSLayoutAttributeBottom
                            multiplier:1.0 constant:8]
[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                toItem:label2 attribute:NSLayoutAttributeBottom
                            multiplier:1.0 constant:8]

我猜您可以将所有内容嵌套在 for() 循环中,这样您就不必重复约束

【讨论】:

【参考方案4】:

没有代码。只需在情节提要中进行编辑。

【讨论】:

以上是关于使用 AutoLayout 在 UITableViewCell 中垂直居中多个 UILabel?的主要内容,如果未能解决你的问题,请参考以下文章

UITableView!别再用代码计算行高了

代码适配(Autolayout)

AutoLayout

使用AutoLayout布局适配时,如何提前获得AutoLayout完成适配后的子控件的真实frame

自动布局AutoLayout

如何在 Xcode 6.3 中使用 AutoLayout 创建 ScrollView