UICollectionViewCell 的高度,带有 2 个多行 UILabel / 自调整大小的集合视图单元格

Posted

技术标签:

【中文标题】UICollectionViewCell 的高度,带有 2 个多行 UILabel / 自调整大小的集合视图单元格【英文标题】:Height of UICollectionViewCell with 2 multiline UILabels / self sizing collection view cells 【发布时间】:2017-04-29 00:08:38 【问题描述】:

我有一个UICollectionViewCell 原型,应该如下所示:

在左侧,有一个UIImageView,我将其垂直居中并将其固定在UICollectionViewCell 的开头。

接下来是标题UILabel,我将其固定在UICollectionViewCell 的顶部和末尾。我还将它固定在UIImageView 的末尾。

下面是一个细节UILabel,我将它固定在标题的底部,UICollectionViewCell 的末尾,并限制它与标题具有相同的宽度。

下面是描述UILabel,我将其固定在细节的底部、UICollectionViewCell 的末尾和UICollectionViewCell 的底部。它的宽度也与标题相同。

我想要达到的目标

标题和描述标签的行数为 0(多行),因为我不知道标签在运行时会有多少行。

通过我的自定义UICollectionViewLayout 我为单元格提供目标宽度。现在我需要弄清楚,对于给定的宽度,单元格的高度必须是多少。

我有一个不可见的UICollectionViewCell,我想我可以通过从我的数据源设置模型来计算大小。但我有一个问题。

问题

在我的“尺寸计算单元格”中设置标签的文本后,我该如何处理宽度以及我还需要做什么才能让自动布局系统为单元格计算一个合适的高度然后我可以回到我的UICollectionViewLayout

或者换句话说:我如何告诉单元格使用新的宽度来计算它的高度。

【问题讨论】:

如果我理解得很好,您需要一种方法来动态计算UILabel 的高度,以便您可以添加到您的尺寸计算中? 因为我设置了从上到下(单元格顶部 -> 标题 -> 详细信息 -> 描述 -> 单元格底部)和从左到右(单元格开始 -> 图像 -> 标签 -> 单元格)的约束end ),我希望有一种方法可以说“嘿,单元格,这是你的宽度,你必须有多高才能使所有标签都不会被截断并且所有标签都可见?”。我也已经尝试通过在标签上使用宽度和 CGFloat.max 调用 sizeThatFits(size) 来自己计算高度,但即使我设置的文本是 2 行,它们总是返回 1 行的高度跨度> 【参考方案1】:

将此扩展添加到字符串中:

extension String 
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat 
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return boundingBox.height
    

然后这样做:

let heightOfLabel = self.string.height(withConstrainedWidth: labelWidth, font: UIFont(name: "HelveticaNeue", size: 15)!)

您将获得具有该字体和该宽度的标签的高度。之后,您可以总结标签高度并将其提供给单元格。

【讨论】:

感谢方便的扩展,我很感激。但是,我采用了不同的方法,现在让 AutoLayout 为我处理大小调整。我不确定您的方法是否更有效地使用 AutoLayout 和 UIStackView,如果它们有内容,我不必检查所有 3 个标签。例如,当底部标签完全为空时,我的单元格大小错误,而 UIStackView 现在完全删除了标签并且看起来仍然正确(检查我的其他答案) 谢谢!将检查它@xxtesaxx【参考方案2】:

好吧,看来我误解了如何使用 sizeThatFits。不过,我现在采用了不同的方法。这就是我为获得自定尺寸单元所做的工作:

我把三个标签放在一个垂直的UIStackView 我把UIImageViewUIStackView 放在一个水平的UIStackView 我将父堆栈视图固定到单元格的左侧、右侧、顶部和底部,其中底部约束 >= 0 而不是 = 0 我在UICollectionViewLayout 中使用协议来询问给定宽度的高度 在我的UICollectionViewController 中,我实现了协议,并在我注册单元的地方,我还实例化了一个用于在协议函数中测量的单元 在协议中,我首先获取模型对象,然后将模型传递给我的测量单元,我将其保存在视图控制器中的实例变量中 然后我在我的单元格上调用 getHeight(forWidth)。在这个函数中,我将单元格frame.size.height 设置为一个非常大的数字。然后我使用AutoLayout计算实际高度(setNeedsDisplay(),layoutIfNeeded()) 我需要的高度是父堆栈视图的高度加上边距

我希望这对将来像我这样的人有所帮助。 I also wrote a small blog post with some code samples of what I'm doing.

【讨论】:

以上是关于UICollectionViewCell 的高度,带有 2 个多行 UILabel / 自调整大小的集合视图单元格的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewCell 和 UICollectionView 的高度相等

UICollectionViewCell 中的动态高度 noScrollable UICollectionView

单击按钮 UICollectionViewCell 宽度和高度更改

UICollectionViewCell 具有 2 列网格和动态高度

UICollectionViewCell - 当其内容改变时动画单元格高度改变

UICollectionViewCell 的子视图的宽度和高度为零