在“cellForRowAt”中激活 NSLayoutConstraint 直到滚动后才会呈现

Activating NSLayoutConstraint in `cellForRowAt` is not rendering until after scrolling

我需要支持 UITableViewAutomaticDimension(对于动态高度),但约束有所不同:有些需要处于活动状态,有些则不需要。

我设置故事板 aConstraint 未安装 ,并且安装了 bConstraint。我 activate/deactivate 他们在 tableView(_:cellForRowAt:) 需要他们。

class ViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView! {
        didSet {
            tableView.estimatedRowHeight = 10
            tableView.rowHeight = UITableViewAutomaticDimension
        }
    }
}

class MyTableViewCell: UITableViewCell {
    @IBOutlet var aConstraint: NSLayoutConstraint!
    @IBOutlet var bConstraint: NSLayoutConstraint!
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! MyTableViewCell
        cell.contentView.translatesAutoresizingMaskIntoConstraints = false
        if indexPath.row % 2 == 0 {
            NSLayoutConstraint.deactivate([cell.aConstraint])
            NSLayoutConstraint.activate([cell.bConstraint])
        } else {
            NSLayoutConstraint.deactivate([cell.bConstraint])
            NSLayoutConstraint.activate([cell.aConstraint])
        }
        return cell
    }
}

问题

初始可见布局忽略了所有这些activations/deactivations,并且所有单元格都与原始故事板状态相同。

您会注意到只有在滚动后才会应用正确的约束。

尝试次数

我确实尝试了一些但没有成功cell.setNeedsUpdateConstraints(); cell.updateConstraintsIfNeeded(); cell.layoutIfNeeded(); ...

示例项目共享于 https://github.com/Coeur/dynamic-cell-height

在代码中设置约束的几个问题。

1.

UILabel intrinsicContentSize 将参与自动布局。 自动布局系统将根据 intrinsicContentSize 创建宽度和高度约束。

您在 xib 文件中明确设置了标签的高度约束,导致歧义,然后添加了垂直中心 Y 约束来解决问题。

2

如果您想尝试激活或停用约束,您可能希望使用简单的 UIView 来实现。

3

如果要做各种高度的行,利用intrinsicContentSize,设置UILabel的preferredWidth。

同时安装 'aConstraint' 和 'bConstraint' 的设置故事板,但将较低的优先级放在 'aConstraint' 上以删除警告并且有效:)