Reputation: 11242
I want to add a gradient to part of a custom UITableViewCell
. This is my gradient Code.
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)
}
This is my gradientView code.
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()
is called in the layoutSubiviews()
method. But the real height and width don't seem to be reflecting until the first reuse of the cell.
Upvotes: 1
Views: 2343
Reputation: 2142
Create a global variable inside the cell.
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
}()
Then add this gradient layer in the initialize method where you are adding UI components.
Now you have to update the frame of the gradient layer.
override func layoutSubviews() {
super.layoutSubviews()
updateGradientFrame()
}
private func updateGradientFrame() {
gradientLayer.frame = // set your frame here...
}
Upvotes: 0
Reputation: 1158
Your TableViewCell does not have a frame yet. You may print the frame to check that, it will be a zero frame.
Move the addGradientView method to the layoutSubView override.
override func layoutSubviews() {
super.layoutSubviews()
addGradient()
}
Edit:
I see that you have mentioned it didn't work in layoutSubView. I believe there is some problem in the way you are calling the method. The below code works for me
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)
}
}
EDIT 2: It would be better if you move the didMoveToWindow
Upvotes: 2
Reputation: 4669
Option 1: Call your addGradient()
from tableview's willDisplayCell
delegate method.
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell is YourCustomTableViewCell {
(cell as! YourCustomTableViewCell).addGradient()
}
}
Make sure you add the gradient once. Because of the cell reuse addGradient()
may get called several times on the same cell. So better rename your function to addGradientfNeeded()
and adjust its logic accordingly.
Option 2:
Instead of adding your gradient in willDisplay
method, add the gradient view and the layer in the cell (once) and only update the frame of the gradient layer.
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell is YourCustomTableViewCell {
(cell as! YourCustomTableViewCell).updateGradientLayerFrame()
}
}
Option 3:
Create a GradientView
class and add it either in the interface builder or programatically to your cell, the gradient will resize as the view's frame changes:
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!)
}
}
Upvotes: 3