Johan van den Berg
Johan van den Berg

Reputation: 15

gradient layer in Swift UITableView

I want to create a gradient background layer in each row of a UITableView in Swift. In the cellForRowAt function I have this piece of code to draw the gradient layer.

guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PlayerTableViewCell else { fatalError("The dequeued cell is not an instance of PlayerTableViewCell") }

// set background color for the cell
let newLayer = CAGradientLayer()
newLayer.colors = [UIColor.black.cgColor, UIColor.darkGray.cgColor ]
newLayer.frame = cell.frame
cell.layer.addSublayer(newLayer)
cell.layer.insertSublayer(newLayer, at: 0)

When I run this code, only the first entry in the table has the gradient layer, the other cells have the default background. Do I need to add something?

Missing background gradient color in table cells

Upvotes: 0

Views: 2784

Answers (2)

Milan Nosáľ
Milan Nosáľ

Reputation: 19747

The problem is that the gradientLayer does not update its bounds when the frame of the superview changes - so when the superview changes its frame, the gradientLayer will still keep the same bounds. You need to update its bounds in layoutSubviews.

I would go with @Jay's answer, but there are some issues there:

var gradientLayer: CAGradientLayer = CAGradientLayer()


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

    // insert it only once
    gradientLayer.colors = [UIColor.black.cgColor, UIColor.darkGray.cgColor ]
    contentView.layer.insertSublayer(gradientLayer, at: 0)

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func layoutSubviews() {
    super.layoutSubviews()
    // here we just need to update the frame
    gradientLayer.frame = contentView.frame
}

I have tested it and it works just fine (well, @Jay's answer seems to be working too for that matter).

Upvotes: 4

Jay
Jay

Reputation: 2661

Why not add it within the subclass of the cell? This way you can also remove it in the prepareForReuse as well, so you aren't adding multiples to the cell?

var newLayer:CAGradientLayer!

override func layoutSubviews() {
    super.layoutSubviews()
    //Code to insert the gradient here.
    newLayer = CAGradientLayer()
    newLayer.frame = contentView.frame
    newLayer.colors = [UIColor.black.cgColor, UIColor.darkGray.cgColor ]
    contentView.layer.insertSublayer(newLayer, at: 0)
}

Upvotes: 4

Related Questions