UITableView动态单元格高度在转换或旋转时中断

时间:2014-11-06 07:40:35

标签: ios uitableview swift autolayout

目前我正在处理快速和动态的表格单元格高度。我在xcode6.1上为iOS8.1开发了一个简单的应用程序:https://github.com/ArtworkAD/DynamicCellTest

因此,要获得与细胞内容一致的细胞高度,我会执行以下操作:

    故事板中的
  • 将标签行设置为0
  • 将标签字体设置为系统
  • 为单元格中的标签设置约束
  • 添加self.tableView.rowHeight = UITableViewAutomaticDimension
  • 不要覆盖heightForRowAtIndex方法

需要最少的代码:

class MyTableViewController: UITableViewController {

    var entries:Array<String> = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        //create dummy content
        var i = 0
        while i < 10 {
            entries.append("\(i) Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor")
            entries.append("\(i+1) Lorem ipsum dolor sit amet")
            i = i + 2;
        }

        self.tableView.rowHeight = UITableViewAutomaticDimension

    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int)  -> Int {
        return self.entries.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = self.tableView.dequeueReusableCellWithIdentifier("basic_cell", forIndexPath: indexPath) as UITableViewCell

        var label = cell.viewWithTag(13)

        if let unwrappedLabel = label as? UILabel {
            unwrappedLabel.text = self.entries[indexPath.row]
        }

        return cell
    }
}

左图显示上述代码的结果。细胞高度随着标签的内容而增长,一切都很好。但是,当您将显示指示器单击到详细信息视图并再次向后移动时,您将获得正确的图像。为什么会发生这种情况?

enter image description here

此问题的一个不好的解决方案是覆盖此方法:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    self.tableView.reloadData()
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.tableView.reloadData()
}

override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    self.tableView.reloadData()
}

这样就解决了上述问题,但这个解决方案似乎不对?它的一个副作用是,当调用self.tableView.reloadData()时,表视图端口跳转到第一个看起来不太好的单元格。

有谁知道我做错了什么?随意克隆我的回购https://github.com/ArtworkAD/DynamicCellTest并测试它。

5 个答案:

答案 0 :(得分:4)

添加此功能似乎可以解决轮换问题。

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    self.tableView.estimatedRowHeight = 36.5
}

但是,我有另一种情况,单元格中有4个标签,它们有相同的旋转问题,添加这还不够,我最终用重新加载的可见单元替换self.tableView.estimatedRowHeight = 36.5

答案 1 :(得分:1)

我通过覆盖tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath)对象中的UITableViewDelegate来解决这个问题。

func tableView(tableView: UITableView, 
               estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) 
               -> CGFloat {
    return 200
}

更改确切的返回值显然没有效果。细胞总是适当自我调整大小。我不知道为什么提供估计的高度导致自动布局开始,但确实如此。 iOS 8.1.2,Xcode 6.1。

答案 2 :(得分:0)

该链接提供了对需要完成的内容的良好解释。

Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

针对您的具体问题,您缺少两行代码。

viewDidLoad添加tableView.rowHeight

下的self.tableView.estimatedRowHeight = 64

以上将允许tableView为屏幕外单元格分配估计的高度值以提高性能,并且还计算滚动条高度。

主要问题是unwrappedLabel.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)中缺少cellForRowAtIndexPath这会告诉标签其首选的最大宽度,因此可以计算多行文字所需的高度。通常你会在表视图单元子类中执行此操作。

我已在您的项目中对此进行了测试,并且可以正常运行

答案 3 :(得分:0)

您必须设置estimatedRowHeight

// setup automatic row height
self.tableView.rowHeight = UITableViewAutomaticDimension

// whatever you think is the approximate row height
self.tableView.estimatedRowHeight = 44

答案 4 :(得分:-2)

此处还遇到了另一种选择http://useyourloaf.com/blog/2014/08/07/self-sizing-table-view-cells.html。评论提到 -

在从cellForRowAtIndexPath返回之前,只需将单元格布局设为子视图:

[cell setNeedsDisplay];
[cell layoutIfNeeded];

Check this