【问题标题】:iOS8 self-sizing static TableView cells with Interface BuilderiOS8 使用 Interface Builder 自行调整大小的静态 TableView 单元格
【发布时间】:2024-01-05 23:42:02
【问题描述】:

我很高兴能够直接在 Xcode 中构建我的静态 TableViews,使用自动布局来支持动态类型,正如 WWDC2014 What's New in Table and Collection Views 中提到的那样。

我更喜欢严格使用 Xcode/Interface Builder 和故事板来处理自动布局。当我这样做时,不知何故 TableView 单元格没有调整大小,我确定我错过了一些简单的东西。

为了重现这一点,使用 Xcode 7 beta 5,我:

  • 创建了一个新的单视图项目。
  • 将 Storyboard 入口点设置为新的 UITableViewController。
  • 使其成为具有分组样式的静态表格视图。
  • 在第一行添加了一个标签。为顶部、底部、左侧和右侧添加了约束。
  • 将标签字体设置为“正文”。
  • 添加到 ViewDidLoad:

    self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 44.0;

  • 运行它并在设置中调整动态类型。虽然字体发生变化,但 TableView 高度仍停留在明显的默认值 44 并截断标签。

这是一个GitHub repository,它是上述结果。

为什么自动布局不会导致 TableView 扩展以填充必要的空间以适应新的更大的标签文本?

我发现了有关该主题的精彩帖子,例如以下内容,并热衷于使用代码设置约束here

我没有在纯 Interface Builder 中找到任何这样做的示例。确定这是完全可能的吗?

更新

我已更新 GitHub 源代码以包含第二个表格行,其中包含 ImageView 而不是 UILabel;它显示了同样的问题:

此外,当我在标签或图像视图上设置显式高度约束时,我会生成以下内容。问题似乎是我没有设置的“UIView-Encapsulated-Layout-Height”约束。我猜它的生成是因为在 IB 的静态表格视图中,行高设置(默认)为 44。

Unable to simultaneously satisfy constraints.
...

"<NSLayoutConstraint:0x7fa371f39e30 V:[UILabel:0x7fa371f38d30'Label'(20)]>",
"<NSLayoutConstraint:0x7fa371c39160 UILabel:0x7fa371f38d30'Label'.top == UITableViewCellContentView:0x7fa371e17dc0.topMargin>",
"<NSLayoutConstraint:0x7fa371c393c0 UITableViewCellContentView:0x7fa371e17dc0.bottomMargin == UILabel:0x7fa371f38d30'Label'.bottom>",
"<NSLayoutConstraint:0x7fa371f41a40 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fa371e17dc0(43.5)]>"

但是 ViewDidLoad 中的 this 不应该覆盖 this 吗?

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0;

自动调整大小的表格视图单元格是否根本不适用于静态表格视图?

更新 2

我使用动态原型而不是静态表格视图构建了相同的东西,并且一切正常:

它确实似乎是静态与动态原型表。静态表格视图单元格未正确展开。

我没有看到 WWDC 视频中提到动态与静态,所以在这一点上,我将其归结为一个错误。如果我学到任何新东西会更新。

我更新了上面的 GitHub 存储库,以显示静态(损坏)和动态(工作)表视图的示例。

【问题讨论】:

标签: ios xcode uitableview ios8 autolayout


【解决方案1】:

对于静态表格视图单元格,您不能在 ViewDidLoad 中使用 UITableViewAutomaticDimension。相反,请使用覆盖函数 heightForRowAt。我的 viewDidLoad 里面什么都没有。我在 ViewDidLoad 上面添加了这两个覆盖函数。

//第一个覆盖每行的高度,使其自动调整大小。

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return UITableViewAutomaticDimension

    }

//这给出了调整大小之前行高的估计值

    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {

        return 100
    }

只要你有上、下、左、右布局约束,一切都应该调整大小。

【讨论】:

    【解决方案2】:

    答案:

    这是 Xcode7b5 中的一个错误。我刚刚按照 Xcode 6.4 和 Xcode 7b5 中的相同步骤确认了这一点。

    1. 创建新的单一视图应用程序
    2. 新文件。 Cocoa 类“MyStaticTableViewController”,UITableViewController 的子类。
    3. 在 Storyboard 中,拖入新的 Table View Controller。
    4. 将类更改为 MyStaticTableViewController。
    5. 将故事板入口点拖到新的 VC。
    6. 删除原VC。
    7. 将新 VC 的类更改为 MyStaticTableViewController。
    8. 选择表视图。将内容更改为静态单元格并将样式更改为分组。
    9. 将新标签拖到第一个表格视图单元格。将字体更改为正文。将顶部、底部、左侧、右侧约束设置为 0 并更新帧。
    10. 在 MyStaticTableViewController.m 中,添加:
     - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.tableView.rowHeight = UITableViewAutomaticDimension;
        self.tableView.estimatedRowHeight = 44.0;
    
    }
    
    1. 使用动态类型验证增加大小也会导致表格行扩展。

    Xcode 6.4 创建的项目按预期工作 - 表格视图单元格展开以适合标签。

    Xcode 7b5 创建的项目如原问题所述失败。

    有趣的是,如果使用 Xcode7 打开 Xcode6 项目,它也可以正常工作。这与 Xcode7 如何创建项目或故事板有关。

    更新

    我比较了 .storyboard 文件,在损坏的 Xcode7b5 的 tableView 条目下,定义了一个 rect:

    <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
    

    我删除了这一行,现在表格视图单元格似乎可以正确调整大小了!

    更新 2

    关键问题似乎是 XML 文件中每个“tableViewCell”条目下留下的“rect”条目。破解这些就是解决这个问题的方法。

    更新 3

    归档雷达:

    “工程部门已确定您的错误报告 (22311571) 与另一个问题 (17995201) 重复,将被关闭。”

    【讨论】:

    • 这解决了我的一个项目中的问题,但在另一个项目中,单元格仍然不会调整大小。你还有别的想法吗?我正在使用 Xcode 7。
    • 抱歉,这是我的白鲸。我想如果底层的 XML 文件最初是用一个搞砸的 Xcode 版本生成的,它可能仍然会搞砸;如果可能的话,可能想重新开始。
    • 直到我也覆盖了tableView:heightForRowAtIndexPath: 以返回UITableViewAutomaticDimension,我的才工作
    • 覆盖 heightForRowAtIndexPath 是我在 Xcode 8.3.2 中完成这项工作所需要做的一切。谢谢@JohnStewart
    【解决方案3】:

    我没有时间看代码,但我几乎可以肯定问题出在标签上。字体大小会改变,但标签的大小不会。我怀疑是因为文本在占据整行后没有被截断,所以留下了一点边距。

    做一个快速测试:为文本标签添加彩色背景。我敢打赌,你会注意到它没有增长。如果没有,请看这里:Adjust UILabel height depending on the text

    【讨论】:

    • 你说得对,巴特塞克。为 UILabel 背景着色确认标签没有垂直扩展以适应文本。当我在标签上设置手动高度约束时,我可以看到存在无法满足的约束,包括:&lt;NSLayoutConstraint:0x7f94d84151a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94d86358e0(43.5)]&gt; - 我认为答案是找出这个约束(UIView-Encapsulated-Layout-Height)来自哪里!我在 IB 的某个地方打赌,我缺少一个复选框。
    • 经过今天的实验,我认为问题不在于标签,而在于内容视图。无论我做什么,都有一个约束UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f8a8362e9e0(43.5)]&gt; - 这似乎是因为在 IB 中,行高设置为 44。我能找到的所有示例都是关于动态表视图的;这是静态的,我想知道这是否是问题所在。我已经用带有突出显示背景的版本更新了上面的 GitHub 链接,用于标签和图像视图。也不是“推出”表格视图单元格。
    • 嗯,这听起来很时髦。自从我上次跳入编程接口地狱后使用 IB 以来,IB 发生了很大变化,但是是的,看起来某处存在与其他地方冲突的约束......
    最近更新 更多