Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why gradient layer in UITableViewCell not cover entire frame?

I try to make a standard gradient top-bottom with long UIView. But it's not full. The nib is part of UITableViewCell, so I don't have access to viewDidLayoutSubviews() as in this thread.

enter image description here

I've tried to call contentView.layoutIfNeeded() from the code version of this view. I called it when UITableView cellForRowAtIndexPath gets called. But it's no effect.

I prepare the gradient in awakeFromNib().

let colors = [
            UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0).cgColor,
            UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0).cgColor]
let gradient = CAGradientLayer()
gradient.frame = gradientView.bounds
gradient.colors = colors
gradientView.layer.insertSublayer(gradient, at: 0) 

Is there something wrong with my code?

like image 589
Seto Avatar asked Dec 22 '17 07:12

Seto


2 Answers

You should use view's boundsinstead of frame, because your layer is inside of the view, and the frame may have an offset.

The layout of the view is changed after awakeFromNib. So you should resize the layer in layoutSubviews of the view. For this create a property gradient and:

let gradient: CAGradientLayer = CAGradientLayer()

override func awakeFromNib() {
    ...
    let colors = [
                UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0).cgColor,
                UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0).cgColor]
    gradient.frame = bounds
    gradient.colors = colors
    gradientView.layer.insertSublayer(gradient, at: 0) 
    ...
}

override func layoutSubviews() {
    super.layoutSubviews()
    gradient.frame = bounds
}

EDIT: An alternative is a custom view with own layer class:

public class GradientLayer: UIView {
    @IBInspectable var startColor: UIColor! = UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0)
    @IBInspectable var endColor: UIColor! = UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0)

    override class var layerClass : AnyClass {
        return CAGradientLayer.self
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        let colors = [ startColor.cgColor, endColor.cgColor ]
        if let gradient = self.layer as? CAGradientLayer {
            gradient.colors = colors
        }
    }
}

This is more elegant, because you can replace the static colors with IB inspectables, and you have a reusable component view.

like image 185
clemens Avatar answered Sep 22 '22 17:09

clemens


 override func layoutSubviews() {
        super.layoutSubviews()

        if let gradient = baseView.layer.sublayers?[0] as? CAGradientLayer {
            gradient.frame = self.bounds
        }
 }
like image 26
Svitlana Avatar answered Sep 23 '22 17:09

Svitlana