【问题标题】:Why does modally presenting a view controller break Auto Layout in my table view?为什么模态显示视图控制器会在我的表格视图中破坏自动布局?
【发布时间】:2015-01-17 19:34:07
【问题描述】:

示例项目: http://cl.ly/1o2K2m2r262q

我有一个 UITableView 自定义单元格,它们的高度是从自动布局中自动计算出来的。自定义单元格中有三个标签,每个标签与内容视图之间有垂直间距,并从左侧推开。

当我输入数据并加载时效果很好。

但是,当我从托管表格视图的视图控制器模态显示视图控制器时,我注意到它完全破坏了自动布局,因为我返回到原始视图控制器。

这是什么原因造成的?我将数据填充到一个简单的数组中,该数组充当表视图数据源的模型,然后它就是自动布局。这是一个如此简单的项目,我很困惑它会在哪里搞砸。

补充:我很欣赏 rdelmar 的回答,但我简直不敢相信现在没有一个单个应用程序可以利用 iOS 的这种动态单元格功能8 不会产生非常跳跃的表格视图。这将非常引人注目。一定有人想出了一种方法来完成这项工作,否则他们永远不会发货。

【问题讨论】:

  • 进行故事板建议的更改以消除红色警告箭头,然后在viewWillDisappear中添加self.tableView.estimatedRowHeight = 166.0
  • @gabbler 他们并不总是那么高。它似乎仍然跳回错误的滚动位置。
  • @DougSmith,是的,它很跳跃,tableViewcontentsize 在滚动时会发生变化。当你回来时,contentsize 和`contentOffset` 将在viewWillAppearviewDidAppear 调用之间变化。我认为您可以手动计算单元格高度来解决此问题。我做了一个测试,以保存通过使用viewWillDisappear 中的NSUserDefault 自行调整单元格计算的所有单元格高度,当我回来时,我使用从NSUserDefault 检索到的单元格高度,并且跳跃行为消失了。

标签: ios uitableview uiview autolayout nslayoutconstraint


【解决方案1】:

由于模式视图,问题没有发生。

这是由于您为表格视图指定的行高。目前是 44,将其更改为 200 或更大,一切都会正常工作。

还要检查 Storyboard 文件中的警告。

【讨论】:

  • 这似乎有帮助,但是当点击一个单元格时,返回表格视图中的偏移量/位置仍然被推送/不是应该的。
【解决方案2】:

解决方案比您想象的要容易得多。您已要求情节提要构建一个行高为 44 的表格视图。在情节提要中选择您的表格视图并检查:

您必须将 tableView 初始行高设置为大于您认为单元格会扩展的值,例如 200 甚至更多:

然后,当 iOS 尝试构建一个高度为 200 的新单元格时,它会填充标签,计算大小,然后缩小单元格。

为什么会这样?

我认为 - 不确定 - 线索是 iOS 构建 tableViews 的方式。 iOS 总是在 iPhone 上显示 8-10 个单元格,如果单元格最初大于它的实际计算高度,则 iOS 会缩小单元格并创建/出列一个新单元格以显示 - 如果需要 - 。如果单元格需要更大,那么iOS 可能需要隐藏最初要显示的行,然后它会拒绝扩大您的单元格。这就是为什么您应该始终更喜欢建造较大的细胞而不是高度较小的细胞。

【讨论】:

  • 我将它设置为 200,但是当点击一个单元格,然后返回时,表格视图中的偏移量/位置仍然关闭。
  • 我试过这个,它在你的示例项目中工作。您是指 tableView 或某些标签的偏移量?
【解决方案3】:

问题在于标签的抗压性: 您已经描述了,哪个标签更能抵抗高度变化: 尝试为标签的 Content Hugging Priority -> Vertical 和 Content Compression Resistance Priority -> Vertical 设置不同的值:

  • 《动物小清单》
  • “动物列表”
  • “更小的列表”

您也使用自动 UITableView 单元格的高度计算,但您需要为其设置表格:

override func awakeFromNib() {
    super.awakeFromNib()
    tableView.estimatedRowHeight = 200; // You need approximately calculate this value by yourself, used mostly for the scroll indicator displaying
    tableView.rowHeight = UITableViewAutomaticDimension;
}

或检查您更新的项目 https://dl.dropboxusercontent.com/u/48223929/LayoutingTest.zip

【讨论】:

  • 当我点击 Go 并返回时,问题仍然存在。细胞仍然一团糟。
  • @DougSmith 你说得对,我的回答不完整。我更新了它
  • 它工作得更好,但在您的示例项目中仍然偶尔会出现点击单元格的问题(在这里很容易看到,但在模态中也可以看到),然后返回时偏移量会发生变化。
【解决方案4】:

你有几个问题。在情节提要中,场景列表中有一个红色的警告箭头。你不应该忽视这一点。单击它并进行它建议的更改(首先执行压缩阻力值,我认为拥抱它的内容会自行消失)。

在 MasterViewController 的 viewDidLoad 中,添加你需要的自调整单元格的这两行,

self.tableView.estimatedRowHeight = 120
self.tableView.rowHeight = UITableViewAutomaticDimension // you may not need this one, I think it might be the default now

最后,我发现当我在故事板中制作单元格时(而不是在代码中),我需要将以下方法添加到单元格类中,因此布局会立即发生(否则它不会布局正确,直到您滚动或旋转),

override func didMoveToSuperview() {
        self.layoutIfNeeded()
    }

【讨论】:

  • 奇怪的是shows no warnings in my Storyboard。其余的工作虽然相当好,但是通过实施的建议,当我滚动时,点击一个单元格或点击“Go”按钮来呈现视图控制器,我在滚动视图中的位置会改变,但只是有时。这是为什么呢?
  • @DougSmith,我认为这与您正在估计行的高度有关,因此它们不准确,并且估计的高度用于设置 contentSize表视图。如果您滚动到表格视图的底部,然后返回到其中一行,则会计算实际高度,并且该影响将消失(或至少最小化)。
  • 我应该如何完美估计每个单元格的大小,尤其是动态类型和动态高度取决于内容?用户不会期望处于一个内容偏移量,并且当他们返回时会处于不同的内容偏移量。一定有别的东西。
  • @DougSmith,是的,有。您可以使用旧方法来计算 heightForRowAtIndexPath 中每个单元格的高度——在显示表格视图之前,这对每一行都已完成。如果您需要支持 iOS 7,则无论如何都需要这样做。我已经看到一些讨论,您看到的问题是一个错误。
  • 目前自动高度计算非常有问题。保持原样或离开它。并打开 Apple 的错误报告,以便他们通过 iOS 10 修复它(可能)。;-)
猜你喜欢
  • 1970-01-01
  • 2013-07-16
  • 2015-10-15
  • 1970-01-01
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多