KFDoom
KFDoom

Reputation: 634

Gradient Layer covers all items in Collection View with no respect of spacing

So I'm using a third party library called Scaling Carousel and for the most part it's been pretty good but for some reason when I try to customize it and add gradient layers to it or even a shadow it doesnt get affixed properly? I've included a picture below for reference.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)

        var view = UILabel()

        view.frame = CGRect(x: 0, y: 0, width: 236, height: 130)

        let layer0 = CAGradientLayer()

               layer0.colors = [

                 UIColor(red: 1, green: 0.46, blue: 0.467, alpha: 1).cgColor,

                 UIColor(red: 1, green: 0.36, blue: 0.369, alpha: 1).cgColor

               ]

               layer0.locations = [0, 1]

               layer0.startPoint = CGPoint(x: 0.25, y: 0.5)

               layer0.endPoint = CGPoint(x: 0.75, y: 0.5)

               layer0.transform = CATransform3DMakeAffineTransform(CGAffineTransform(a: -1, b: 1, c: -1, d: -2.48, tx: 1.5, ty: 1.24))

        layer0.bounds = view.bounds.insetBy(dx: -0.5*view.bounds.size.width, dy: -0.5*view.bounds.size.height)

        layer0.position = view.center


        view.layer.addSublayer(layer0)

        cell.addSubview(view)


        if let scalingCell = cell as? ScalingCarouselCell {
            scalingCell.mainView.backgroundColor = .white

        }

Here's the scalingcarousel code

open class ScalingCarouselCell: UICollectionViewCell {

    // MARK: - Properties (Public)

    /// The minimum value to scale to, should be set between 0 and 1
    open var scaleMinimum: CGFloat = 0.9

    /// Divisior used when calculating the scale value.
    /// Lower values cause a greater difference in scale between subsequent cells.
    open var scaleDivisor: CGFloat = 10.0

    /// The minimum value to alpha to, should be set between 0 and 1
    open var alphaMinimum: CGFloat = 0.85

    // MARK: - IBOutlets

    // This property should be connected to the main cell subview
    @IBOutlet public var mainView: UIView!

    // MARK: - Overrides

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

        guard let carouselView = superview as? ScalingCarouselView else { return }

        scale(withCarouselInset: carouselView.inset)
    }

    override open func prepareForReuse() {
        super.prepareForReuse()
        mainView.transform = CGAffineTransform.identity
        mainView.alpha = 1.0

    }


    /// Scale the cell when it is scrolled
    ///
    /// - parameter carouselInset: The inset of the related SPBCarousel view
    open func scale(withCarouselInset carouselInset: CGFloat) {

        // Ensure we have a superView, and mainView
        guard let superview = superview,
            let mainView = mainView else { return }

        // Get our absolute origin value
        let originX = superview.convert(frame, to: superview.superview).origin.x

        // Calculate our actual origin.x value using our inset
        let originXActual = originX - carouselInset

        let width = frame.size.width

        // Calculate our scale values
        let scaleCalculator = abs(width - abs(originXActual))
        let percentageScale = (scaleCalculator/width)

        //Calculate distance between our carousel views
        let scaleValue = scaleMinimum
        //Add the following line for a greater carousel effect.
        //+ (percentageScale/scaleDivisor)

        let alphaValue = alphaMinimum
            + (percentageScale/scaleDivisor)

        let affineIdentity = CGAffineTransform.identity

        // Scale our mainView and set it's alpha value
        mainView.transform = affineIdentity.scaledBy(x: scaleValue, y: scaleValue)
        mainView.alpha = 1.0

        // ..also..round the corners
        mainView.layer.cornerRadius = 28

without gradient code with gradient code

Upvotes: 0

Views: 457

Answers (1)

DonMag
DonMag

Reputation: 77647

My suggestion is to use a UIView subclass with the gradient and corner radius logic inside.

So, first, add this code to your project:

@IBDesignable
class KFGradientView: UIView {

    override class var layerClass: AnyClass {
        return CAGradientLayer.self
    }

    private var gLayer: CAGradientLayer {
        return self.layer as! CAGradientLayer
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    func commonInit() {
        gLayer.type = .axial

        gLayer.colors = [
            UIColor(red: 1, green: 0.46, blue: 0.467, alpha: 1).cgColor,
            UIColor(red: 1, green: 0.36, blue: 0.369, alpha: 1).cgColor
        ]
        gLayer.locations = [0, 1]
        gLayer.startPoint = CGPoint(x: 0.25, y: 0.5)
        gLayer.endPoint = CGPoint(x: 0.75, y: 0.5)

        // exaggerated colors so it's obvious
        // remove or comment-out this to use original red-ish colors
        gLayer.colors = [
            UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1).cgColor,
            UIColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1).cgColor
        ]

        gLayer.cornerRadius = 28
    }

}

Next, for a quick test, add a view controller to your Storyboard and add a UIView subview. Change that view's class to KFGradientView (ignore the scratchy -- you should see the name of your project there):

enter image description here

From the top menu bar, select Editor -> Refresh All Views (or have Automatically Refresh Views checked). You should see this:

enter image description here

Assuming you do, go to your Collection View Cell prototype, and change the class of mainView from UIView to KFGradientView. You should see the same thing happen there.

Then, remove this line from your func scale(...) in your class ScalingCarouselCell: UICollectionViewCell:

mainView.layer.cornerRadius = 28

and change your cellForItemAt func to:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ScalingCarouselCell

    return cell
}

As far as your mainView not getting sized / positioned in the cell correctly, well, that's an entirely different issue. If you can't figure it out, post that as a new question.

Upvotes: 3

Related Questions