skip to Main Content

I’m trying to apply a gradient to a view that is a constraint to the top, left, and right of the collection view but for some reason, the gradient doesn’t cover the whole width of the view that is applied to (see the red in the picture).

View Controller Code:-

extension HomeView : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    1
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as! CollectionCell
    cell.storyImage.image = UIImage(named: storyImages[indexPath.item].mediaURL ?? EMPTY_STR)
    cell.gradientView.frame = cell.storyImage.frame
    return cell
 }

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
  }
}

Cell Code:-

import UIKit

class CollectionCell: UICollectionViewCell {

@IBOutlet weak var sImage: UIImageView!
@IBOutlet weak var gradientView: GradientView!

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

class GradientView: UIView {

override func awakeFromNib() {
    super.awakeFromNib()
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
    gradientLayer.colors = [UIColor.white.cgColor,UIColor.red.withAlphaComponent(0.5).cgColor]
    gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
    gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
    layer.addSublayer(gradientLayer)
   }
}

Output:-

ScreenShot

Main Storyboard

ScreenShot

Question: How to set the width according to the collection view width?

Can someone please explain to me how to do this, I’ve tried with the above code but have no results yet. Please Correct me if I’m doing wrong.

Any help would be greatly appreciated.

2

Answers


  1. It happens because cell’s contenview frame not updating. As the comment says , contentView’s frame is equal to same in xib/storyboard frame in awakeFromNib. Use cell.contentView.layoutIfNeeded() in cellForRowAt

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as! CollectionCell
        cell.contenView.layoutIfNeeded()
        cell.storyImage.image = UIImage(named: storyImages[indexPath.item].mediaURL ?? EMPTY_STR)
        cell.gradientView.frame = cell.storyImage.frame
        return cell
    

    }

    In your cell class ,set layer’s frame in layoutsubview function

     override func layoutSubviews() {
            super.layoutSubviews()
            gradientLayer.frame = self.bounds
    }
    
    Login or Signup to reply.
  2. This line in your cellForItemAt code is a little confusing:

    cell.gradientView.frame = cell.storyImage.frame
    

    In your Storyboard Prototype cell, you should constrain the gradientView to the storyImage view they will both be the same size.

    Also, if you change your GradientView class to this, you don’t have to worry about making separate calls to layout the gradient layer’s frame:

    class GradientView: UIView {
        
        lazy var gradientLayer: CAGradientLayer = self.layer as! CAGradientLayer
        override class var layerClass: AnyClass {
            return CAGradientLayer.self
        }
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        private func commonInit() {
            gradientLayer.colors = [UIColor.white.cgColor,UIColor.red.withAlphaComponent(0.5).cgColor]
            gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
            gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
        }
        
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search