swiftuicollectionviewuicollectionreusableview

Swift UICollectionReusableView didn't update the frame when reuse


I tried to build a multiple section with a same UICollectionReusableView as a decorationItems. But when the view is reused during the scrolling, the gradientLayer inside the ReusableView didn't updated to meet the new section size. I have no ideas what the problem. How can I reset the gradientLayer frame when the UICollectionReusableView reused.

class RoundedBackgroundView: UICollectionReusableView {

    private var insetView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.layer.cornerRadius = 6
        view.clipsToBounds = true
        return view
    }()


    override init(frame: CGRect) {
        super.init(frame: frame)
        let gradientLayer = CAGradientLayer()
        // Set the size of the layer to be equal to size of the display.
        gradientLayer.frame = self.bounds
        // Set an array of Core Graphics colors (.cgColor) to create the gradient.
        gradientLayer.colors = [UIColor(red: 246, green: 186, blue: 58).cgColor, UIColor(red: 233, green: 115, blue: 58).cgColor]
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
        // Rasterize this static layer to improve app performance.
        gradientLayer.shouldRasterize = true
        insetView.layer.addSublayer(gradientLayer)
        addSubview(insetView)

        NSLayoutConstraint.activate([
            insetView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),
            insetView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0),
            insetView.topAnchor.constraint(equalTo: topAnchor),
            insetView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }

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

Solution

  • For reusable views I would always recommend to make a separated view, do all the layout in that view and add this to the cell/reusableView.

    Anyways, the problem is probably, that the bounds aren't set at the init-method. A way to solve it would be adding this function to your reusable view.

    override func layoutSubviews() {
        super.layoutSubviews()
        if insetView.bounds.height > 0 {
           gradientLayer.frame = insetView.bounds
        }
    }