Victor Sanchez
Victor Sanchez

Reputation: 983

UICollectionViewCell - Applying different CAGradientLayer to different UIView

TL;DR: Have 2 views (top and bottom) that need CAGradientLayer. Unexpected behavior is that only Top View displays gradient. Bottom doesn't display Gradient.

In our application, I have a view that has a UICollectionView as seen on the image: Whole device

For each UICollectionViewCell, I created a custom class to do the layout details. On the UICollectionViewCell, I have a "topBackground" and "bottomBackground", which are views that will content labels with info for each Cell:

@IBOutlet weak var topBackground: UIView! 
@IBOutlet weak var bottomBackground: UIView!

The Top and Bottom Views, Labels were displaying correctly and the constraints working.

We decided to add a gradient effect on the Top and Bottom View (see details on image, top gradient marked in red and bottom detail marked in yellow) enter image description here.

For the code, we used the following:

override func layoutSubviews() {
        if !didLayout{                
             // Top View
            let gradientLayer: CAGradientLayer = CAGradientLayer()
            gradientLayer.frame = topBackground.frame
            gradientLayer.colors =
                [UIColor.black.withAlphaComponent(0.5).cgColor, UIColor.black.withAlphaComponent(0).cgColor]
            gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
            gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.9)
            topBackground.layer.insertSublayer(gradientLayer, at: 0)
            topBackground.backgroundColor = .clear
            topBackground.alpha = 0.5

            // Bottom View
            let gradientLayerBottom: CAGradientLayer = CAGradientLayer()
            gradientLayerBottom.frame = bottomBackground.frame
            gradientLayerBottom.colors =
                [UIColor.black.withAlphaComponent(0.5).cgColor, UIColor.black.withAlphaComponent(0).cgColor]
            gradientLayerBottom.startPoint = CGPoint(x: 0.5, y: 0.9)
            gradientLayerBottom.endPoint = CGPoint(x: 0.5, y: 0)
            bottomBackground.layer.insertSublayer(gradientLayerBottom, at: 0)
            bottomBackground.backgroundColor = .clear
            bottomBackground.alpha = 0.5

            didLayout = true
        } else {
            print("already performed layout")
        }
    }

The variable didLayout is to avoid overlapping multiple gradients when scrolling the collection view.

Results:

  1. The Top View is displaying the Gradient (Expected).
  2. Bottom View is not displaying Gradient (Unexpected).

We know the bottom view is there with the constraints working, because if we change the color to other than .clear, it displays the other color. It's just gradientLayerBottom that is not being displayed.

Any ideas on how to get gradientLayerBottom to be displayed?

Upvotes: 0

Views: 632

Answers (1)

Nikunj Kumbhani
Nikunj Kumbhani

Reputation: 3924

Try this

extension UIView{
    func setGradientBackgroundImage(colorTop: UIColor, colorBottom: UIColor) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [colorTop.cgColor, colorBottom.cgColor]
        gradientLayer.frame = bounds
        layer.insertSublayer(gradientLayer, at: 0)
    }
}

Put in UICollectionViewCell class

class CollVwCell : UICollectionViewCell{

    @IBOutlet weak var VwTop: UIView!
    @IBOutlet weak var VwBottom: UIView!

    override func awakeFromNib() {
        super.awakeFromNib()
        DispatchQueue.main.async {
            self.VwTop.setGradientBackgroundImage(colorTop: UIColor.red, colorBottom: UIColor.white)
            self.VwBottom.setGradientBackgroundImage(colorTop: UIColor.white, colorBottom: UIColor.purple)
        }
    }
}

Output:

enter image description here

Upvotes: 1

Related Questions