渐变的UITableViewCell在首次重用单元格之前无法正常工作

时间:2018-07-11 05:01:49

标签: 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, 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
}

addGradient()layoutSubiviews()方法中被调用。但是,直到第一次重新使用单元格时,实际的高度和宽度似乎才能够反映出来。

3 个答案:

答案 0 :(得分:2)

选项1:从表视图的addGradient()委托方法中调用willDisplayCell

public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if cell is YourCustomTableViewCell {
        (cell as! YourCustomTableViewCell).addGradient()
    }
}

确保一次添加渐变。由于单元重用,addGradient()可能在同一单元上被调用多次。因此最好将函数重命名为addGradientfNeeded()并相应地调整其逻辑。

选项2:

与其在willDisplay方法中添加渐变,不如在单元格中添加渐变视图和图层(一次),仅更新渐变图层的框架。

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

选项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!)
    }
}

答案 1 :(得分:0)

您的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)
}

}

enter image description here

编辑2:     最好移动didMoveToWindow

答案 2 :(得分:0)

在单元格内部创建一个全局变量。

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方法中添加此渐变层。

现在,您必须更新渐变层的框架。

override func layoutSubviews() {
    super.layoutSubviews()
    updateGradientFrame()
}

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