首页 > 解决方案 > TableView 计算错误的estimatedHeightForRowAt

问题描述

我正在制作一个类似应用程序的聊天应用程序,其中 tableView 显示动态高度单元格。


单元格的视图和子视图以正确的方式受到限制

这样AutoLayout 可以预测单元格的高度

(顶部、底部、前导、尾随)


但仍然- 正如您在视频中看到的那样 -滚动指示条显示计算了错误的高度:

当出现新行时,它会重新计算高度。

视频: https ://youtu.be/5ydA5yV2O-Q

(第二次尝试向下滚动一切都很好)


代码:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

这是一个简单的问题。有人可以帮我吗?

更新 1.0

添加了github:

https://github.com/krptia/Test

标签: swifttableviewscrollview

解决方案


但仍然 - 正如您在视频中看到的那样 - 滚动指示条显示计算了错误的高度:

所以你想要的是精确的内容高度。

为此,您不能使用 static estimatedRowHeight。您应该执行更正确的估计,如下所示。

    ...

    var sampleCell: WorldMessageCell?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UINib(nibName: "WorldMessageCell", bundle: nil), forCellReuseIdentifier: "WorldMessageCell")

        sampleCell = UINib(nibName: "WorldMessageCell", bundle: nil).instantiate(withOwner: WorldMessageCell.self, options: nil)[0] as? WorldMessageCell
    }

    ...

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        if let cell = sampleCell {
            let text = self.textForRowAt(indexPath)
            // note: this is because of "constrain to margins", which value is actually set after estimation. Do not use them to remove below
            let margin = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 20)
            // without "constrain to margins"
            // let margin = cell.contentView.layoutMargins 
            let maxSize = CGSize(width: tableView.frame.size.width - margin.left - margin.right,
                                 height: CGFloat.greatestFiniteMagnitude)
            let attributes: [NSAttributedString.Key: Any]? = [NSAttributedString.Key.font: cell.messageLabel.font]
            let size: CGRect = (text as NSString).boundingRect(with: maxSize,
                                                                 options: [.usesLineFragmentOrigin], attributes: attributes, context: nil)
            return size.height + margin.top + margin.bottom
        }
        return 100
    }

这太精确(实际上是真实的行高)并且可能很慢,但是您可以进行更近似的估计以进行优化。


推荐阅读