Ios 具有渐变的UITableViewCell在第一次重新使用单元格之前不起作用

Ios 具有渐变的UITableViewCell在第一次重新使用单元格之前不起作用,ios,swift,uitableview,cagradientlayer,Ios,Swift,Uitableview,Cagradientlayer,我想向自定义UITableViewCell的一部分添加渐变。这是我的梯度代码 func addGradient() { gradient = CAGradientLayer() gradient.frame = CGRect(x: 0, y: 0, width: gradientView.frame.width, height: gradientView.frame.height) gradient.colors = [ UIColor(red:0.23,

我想向自定义
UITableViewCell
的一部分添加渐变。这是我的梯度代码

func addGradient() {
    gradient = CAGradientLayer()
    gradient.frame = CGRect(x: 0, y: 0, width: gradientView.frame.width, height: gradientView.frame.height)
    gradient.colors = [
        UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
        UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
    ]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 0.5, y: 0)
    gradient.endPoint = CGPoint(x: 0.5, y: 1)
    gradientView.layer.addSublayer(gradient)
}
这是我的gradientView代码

func addGradientView() {
    containerView.addSubview(gradientView)

    gradientView.translatesAutoresizingMaskIntoConstraints = false
    gradientView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
    gradientView.topAnchor.constraint(equalTo: barChart.bottomAnchor).isActive = true
    gradientView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
    gradientView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
}

layoutSubiviews()
方法中调用
addGradient()
。但是真正的高度和宽度似乎在第一次重用单元格之前不会反映出来。

选项1:从tableview的
willDisplayCell
委托方法调用您的
addGradient()

public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if cell is YourCustomTableViewCell {
        (cell as! YourCustomTableViewCell).addGradient()
    }
}
private let gradientLayer: CAGradientLayer = {
    let layer = CAGradientLayer()
    layer.colors = [UIColor.magenta.cgColor, UIColor.black.cgColor]
    layer.locations = [0.0, 1.0]
    layer.cornerRadius = 5
    layer.masksToBounds = true
    return layer
}()
确保添加一次渐变。由于单元重用,
addGradient()
可能会在同一单元上被多次调用。因此,最好将函数重命名为
addGradientFneed()
,并相应地调整其逻辑

选项2:

不要在
willDisplay
方法中添加渐变,而是在单元格中添加渐变视图和图层(一次),只更新渐变图层的帧

public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if cell is YourCustomTableViewCell {
        (cell as! YourCustomTableViewCell).updateGradientLayerFrame()
    }
}
override func layoutSubviews() {
    super.layoutSubviews()
    updateGradientFrame()
}

private func updateGradientFrame() {
    gradientLayer.frame = // set your frame here...
}
选项3:

创建一个
GradientView
类,并将其添加到界面生成器中或以编程方式添加到单元格中,渐变将随着视图框架的更改而调整大小:

public class GradientView: UIView {
    private var gradientLayer: CAGradientLayer?

    override public func layoutSubviews() {
        super.layoutSubviews()

        guard gradientLayer == nil else {
            gradientLayer?.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
            return
        }

        gradientLayer = CAGradientLayer()
        gradientLayer!.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
        gradientLayer!.colors = [
            UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
            UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
        ]
        gradientLayer!.locations = [0, 1]
        gradientLayer!.startPoint = CGPoint(x: 0.5, y: 0)
        gradientLayer!.endPoint = CGPoint(x: 0.5, y: 1)
        self.layer.addSublayer(gradientLayer!)
    }
}

您的TableViewCell还没有框架。您可以打印帧以检查它是否为零帧

将addGradientView方法移动到layoutSubView替代

override func layoutSubviews() {
    super.layoutSubviews()
    addGradient()
}
编辑:

我看到您提到它在layoutSubView中不起作用。我相信您调用该方法的方式存在一些问题。 下面的代码适用于我

class GradientCell: UITableViewCell {


override func layoutSubviews() {
    super.layoutSubviews()
    print(self.frame)
    addGradient()
}

func addGradient() {
    let gradient = CAGradientLayer()
    gradient.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
    gradient.colors = [
        UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
        UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
    ]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 0.5, y: 0)
    gradient.endPoint = CGPoint(x: 0.5, y: 1)
    self.layer.addSublayer(gradient)
}

}

编辑2:
如果将DIDMOVETOW移动到Windows,则会更好。在单元格内创建一个全局变量

private let gradientLayer: CAGradientLayer = {
    let layer = CAGradientLayer()
    layer.colors = [UIColor.magenta.cgColor, UIColor.black.cgColor]
    layer.locations = [0.0, 1.0]
    layer.cornerRadius = 5
    layer.masksToBounds = true
    return layer
}()
然后在添加UI组件的initialize方法中添加此渐变层

现在您必须更新渐变层的帧

public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if cell is YourCustomTableViewCell {
        (cell as! YourCustomTableViewCell).updateGradientLayerFrame()
    }
}
override func layoutSubviews() {
    super.layoutSubviews()
    updateGradientFrame()
}

private func updateGradientFrame() {
    gradientLayer.frame = // set your frame here...
}

当添加gradientView时,单元似乎还没有它的框架。您可以在单元格xib或序列图像板中查看并尝试绘制渐变,因为没有xib或序列图像板。不添加图层,而是创建新的UIView子类类并覆盖图层属性。使用此选项,您无需将“图幅”设置为“自动”resize@SPatel如果你加上它作为一个答案,我会很高兴地标记它接受。这对我很有用。@RakeshaShastri我用自定义的
GradientView
类方法更新了我的答案。为什么在
cellForRowAt
方法中返回单元格时,GradientView的框架没有设置?简短回答:因为您使用的是自动布局。要详细说明我的简短答案,如果处理的是视图而不是图层,则不会有问题。调用
cellForRowAt
时,您没有正确的帧,但您的视图最终会按预期显示。这是一个不使用约束的层,因此在其视图调整其框架时不会“拉伸”。您可以在使用autolayout设置的子视图框架上尝试它吗?每次调用
layoutSubviews()
时,您都会添加一个层。如果你有更多的单元格并开始上下滚动,你最终会得到包含几个子层的完全黑色单元格。哦,是的,我忘了。我的错。但这可以通过将CAGradientLayer作为类级变量来避免。我会更新。