具有动态 UILabel 和内容压缩/阻力的 UITableViewCell 高度不正确

Posted

技术标签:

【中文标题】具有动态 UILabel 和内容压缩/阻力的 UITableViewCell 高度不正确【英文标题】:Incorrect UITableViewCell Height with Dynamic UILabels and Content Compression/Resistance 【发布时间】:2016-03-03 21:57:42 【问题描述】:

基于 Xcode 7.2.1、ios 9.2

我有一个UITableView,其中的单元格具有自动高度。

tableView.estimatedRowHeight = 80
tableView.rowHeight = UITableViewAutomaticDimension

单元格的布局如下:

UITableViewCell
  contentView
  outerStackView - pinned to top, left, right, bottom edges of the contentView with autolayout
    leftColumnStackView - 38% of width of outerStackView
       topStackView
         label UILabel
         value UILabel
       bottomStackView
         label UILabel
         value UILabel
    middleColumnStackView - 38% of width of outerStackView
      ...
    rightColumnStackView - rest of the width of outerStackView
      ...

单元格中有 6 个标签/值对 - [标签 X:值]。每个标签/值对由 2 个UILabels 组成,它们的内容拥抱和内容压缩阻力属性进行了相应设置,以提供所需的外观。

label.numberOfLines = 0
label.textAlignment = NSTextAlignment.Left
label.setContentCompressionResistancePriority(1000, forAxis: .Horizontal)
label.setContentHuggingPriority(1000, forAxis: .Horizontal)

value.numberOfLines = 0
value.setContentCompressionResistancePriority(500, forAxis: .Horizontal)
value.setContentHuggingPriority(500, forAxis: .Horizontal)

// there are 6 stack views, each containing a label/value pair
// the stack views are .Horizontal alignment, and pinned to the 
// columns they sit in
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(value)

但是,有时单元格高度会正确测量自身,而其他时候会增加一堆额外的空间(有趣的是,额外的空间总是等于如果内容压缩会存在的空间/hugging 未添加到任一标签中)。

这是发生的不一致:

有时是对的:

有时它是错误的:

但是,当我从标签中删除内容压缩/阻力时,单元格始终是正确的高度,但看起来像这样:

有人遇到过类似情况吗?有什么建议吗?

【问题讨论】:

你的约束是什么样的? @beyowulf 所以一切都位于堆栈视图内的堆栈视图内。 1 个外部堆栈视图 -> 3 列堆栈视图内部 -> 在每列内部,2 个堆栈视图,每个内部都有一个标签/值。我可以为有关结构的问题添加一些修饰。 你在哪里打电话label.numberOfLines = 0 label.textAlignment = NSTextAlignment.Left label.setContentCompressionResistancePriority(1000, forAxis: .Horizontal) label.setContentHuggingPriority(1000, forAxis: .Horizontal) etc. 我猜你是在 cellForRowAtIndexPath 中设置压缩和拥抱,有时在自动布局引擎通过之前调用它,有时在我尝试将它移动到你的 UITableViewCell 子类的 awakeFromNib 之后调用。 @beyowulf,我正在以编程方式创建单元格,而不是使用 Storyboard。我在单元格的init() 中设置了compressionhuggingnumberOfLines 等,并为我的UITableView 使用dequeuReusableCellWithIdentifier。你认为有一个等价于 awakeFromNib 的程序单元创建吗? 【参考方案1】:

想通了!

这最终与单元格的 contentView 使用 AutoLayout 定位的方式有关。显然,默认情况下它没有正确布局和计算其子视图的位置。

在我的 UITableViewCell 子类中,我将以下内容添加到我的 init()

contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true
contentView.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true
contentView.topAnchor.constraintEqualToAnchor(topAnchor).active = true
contentView.bottomAnchor.constraintEqualToAnchor(bottomAnchor).active = true

通过将contentView 固定到单元格,UITableViewCell 的高度分配不一致的问题消失了,并且始终显示正确的高度。

这导致 contentView 被拉伸到所有 4 个边缘,这确实会影响其他一些事情(例如 UITableView 编辑翻转到 true 时的动画),但现在我可以解决以其他方式解决这些问题,因为没有任何事情被计算为错误或正在发生出乎意料的事情。

【讨论】:

以上是关于具有动态 UILabel 和内容压缩/阻力的 UITableViewCell 高度不正确的主要内容,如果未能解决你的问题,请参考以下文章

UIStackView 中标签的内容拥抱和压缩问题设置

UILabel 自动收缩不起作用

水平 UIStackView :值 999 或 1000 在水平内容压缩阻力中是不是有任何特殊含义?

如何让 UIlabel 动态地自动跨越多行。在具有多个 UIlabels 的 Tableview 单元格/ContentView 内

具有动态高度的 UITableViewCell 中的多个 UILabel

将 UITableViewCell 的垂直压缩阻力优先级设置为 749