在 heightForRowAt IndexPath 之后 UITableViewCell 的层没有得到更新

Posted

技术标签:

【中文标题】在 heightForRowAt IndexPath 之后 UITableViewCell 的层没有得到更新【英文标题】:UITableViewCell's layer not getting updated after heightForRowAt IndexPath 【发布时间】:2017-09-21 00:37:49 【问题描述】:

我正在更改每个 TableViewCell 的大小:

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

然后,在自定义单元格类中,我将“gradientLayer”作为子层插入到单元格的图层属性中:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    ...
    gradientLayer.frame = self.layer.bounds
    layer.insertSublayer(gradientLayer, at: 0)
    ...

但是,渐变并没有填满整个单元格:

有谁知道为什么会发生这种情况/我该如何解决?

谢谢。

【问题讨论】:

【参考方案1】:

如果您使用普通的UITableViewCell

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)

        // ...

        let gradient =  CAGradientLayer()
        gradient.frame = cell.contentView.frame
        gradient.colors = [UIColor.blue.cgColor, UIColor.yellow.cgColor]
        gradient.locations = [0.0, 1.0]
        cell.contentView.layer.insertSublayer(gradient, at: 0)

        // ...

        return cell
    

您需要确保将渐变添加到 contentView 的图层。

这会很好用。

如果您使用自定义 UITableViewCell 类:

现在,如果您使用的是自定义单元格类,则需要覆盖layoutSubviews() 方法,如下所示:

override func layoutSubviews() 
    super.layoutSubviews()

    gradient.frame = contentView.frame

这可确保您的渐变框架在任何时候都与您的 contentView 框架相同。

您的自定义单元格类将如下所示:

class CustomTableCell: UITableViewCell 

    lazy var gradient : CAGradientLayer = 
        var gradient = CAGradientLayer()
        gradient.colors = [UIColor.blue.cgColor, UIColor.yellow.cgColor]
        gradient.locations = [0.0, 1.0]
        self.contentView.layer.insertSublayer(gradient, at: 0)
        return gradient
    ()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        // ...

    

    override func layoutSubviews() 
        super.layoutSubviews()

        // ...

        gradient.frame = contentView.frame

        // ...

    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)

        // ...
    



如果您有任何其他问题,请告诉我!

【讨论】:

在 init 中设置框架不正确。该点的框架将是单元格的默认框架,这可能不是 heightForRowAtIndexPath 返回的内容。 这就是我对 OP 说要在 layoutSubviews() 中设置的原因! 请不要介意我的复制/粘贴错误,我更新了答案:)。 您显示的初始化代码在这两种情况下都不正确。这就是我的观点。由于尚未应用 heightForRowAtIndexPath,因此永远不应使用该框架。 这对我有用,我相信这对我来说是正确的选择,因为我使用的是自定义单元格。再次感谢您。【参考方案2】:

为什么会这样?我不知道。

但是如果你把渐变放在你的 tableview 的cellForRowAt 中,你会得到:


代码如下:

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


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

    let cell =  tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    let gradient: CAGradientLayer = CAGradientLayer()
    gradient.colors = [UIColor.blue.cgColor, UIColor.red.cgColor]
    gradient.frame = CGRect(x: 0.0, y: 0.0, width: cell.frame.size.width, height: cell.frame.size.height)
    cell.layer.insertSublayer(gradient, at: 0)

    return cell

【讨论】:

没错,这就是我要向@clarus 解释的内容。在调用 cellForRow 方法时,您的 heightForRow 已经运行,因此您可以在此方法中设置渐变框架而不会出现任何问题。【参考方案3】:

初始时的帧大小是单元格的默认帧,来自故事板或任何地方。它不会有你的高度 60(除非匹配),因为单元格只是在 init 中创建,然后它将被调整大小。

您可以在那里添加图层,但在 layoutSubviews 中调整大小或使用约束来自动布局。如果您这样做,渐变将以最终大小填充您的单元格。

【讨论】:

以上是关于在 heightForRowAt IndexPath 之后 UITableViewCell 的层没有得到更新的主要内容,如果未能解决你的问题,请参考以下文章

EXC_BAD_ACCESS 在 heightForRowAt 内时

RxSwift + UITableViewCell 如何在 heightForRowAt 中获取单元格对象

在 heightForRowAt IndexPath 之后 UITableViewCell 的层没有得到更新

indexpath.row 在tableView heightForRowAt 3 后重置

什么时候设置更改 heightForRowAt UITableView 动画被破坏

使 UITableViewCell 适合 UICollectionView 而没有 tableView heightForRowAt