skip to Main Content

I want to add a fade effect to the top of the collection view as in the photo below. The list in this photo is a feature that exists in the live broadcast of Instagram. I tried CAGradientLayer but didn’t get the result I wanted. Thanks in advance for the help.

Instagram Live List: https://i.stack.imgur.com/gUj77.jpg

Edit: I want this effect to always stay at the top of the list. Btw, things I’ve tried with CAGradientLayer:

private func setFadeOut() {
let collectionViewGradient = CAGradientLayer()
collectionViewGradient.colors = [
    UIColor.gray.withAlphaComponent(0.2).cgColor,
    UIColor.gray.withAlphaComponent(0.1).cgColor,
    UIColor.clear.cgColor
]
collectionViewGradient.frame = view.bounds
collectionViewGradient.startPoint = CGPoint(x: 0, y: 0)
collectionViewGradient.endPoint = CGPoint(x: 0, y: 1)
collectionView.layer.insertSublayer(collectionViewGradient, at: 0)
}

2

Answers


  1. You didn’t configured the gradient properly. Your color order was incorrect and you are missing locations.

    Try this:

        private func setFadeOut() {
        let collectionViewGradient = CAGradientLayer()
        collectionViewGradient.colors = [
            UIColor.gray.cgColor,
            UIColor.white.cgColor,
            UIColor.white.cgColor,
            UIColor.gray.cgColor
        ]
        collectionViewGradient.locations = [0, 0.1, 0.9, 1.0]
        collectionViewGradient.frame = view.bounds
        collectionView.layer.insertSublayer(collectionViewGradient, at: 0)
    }
    
    Login or Signup to reply.
  2. You may try using a view class like the one below.
    Place your gradient view wherever you want (top, bottom), set its frame and make sure the z-ordering is ok (bring it to front if needed).
    The distance argument determines the transition region in points.

    An example – if you place it at the top and set its frame height to be 150 and distance to be 100, the gradient will progress over 100 points and the remaining 50 points on top will be pure black (or whatever color you set it to).

    Typically you want to place it so that it transitions over the safe area and the remaining unsafe area is pure black (under the notch etc).

    The view instance needs to be created programmatically but this is what you seem to be doing anyway. It won’t be difficult to modify it for Interface Builder use.

    import UIKit
    
    class EdgeGradientView: UIView {
        
        static override var layerClass: AnyClass {
            return CAGradientLayer.self
        }
        
        enum Placement {
            case top
            case bottom
        }
        
        private let placement: Placement
        private let distance: Int
        private let color: UIColor
        
        init(placement: Placement, distance: Int, color: UIColor) {
            self.placement = placement
            self.distance = distance
            self.color = color
            
            super.init(frame: .zero)
            
            isUserInteractionEnabled = false
    
            configureGradient()
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            
            updateGradient()
        }
    
        private func configureGradient() {
            let gradientLayer = layer as! CAGradientLayer
            gradientLayer.colors = [
                color.cgColor,
                color.cgColor,
                color.withAlphaComponent(0.0).cgColor
            ]
            switch placement {
            case .top:
                gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
                gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
            case .bottom:
                gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
                gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
            }
            
            updateGradient()
    
        }
        
        private func updateGradient() {
            let gradientLayer = layer as! CAGradientLayer
            gradientLayer.locations = [0.0, 1.0 - Double(distance) / Double(bounds.height), 1.0] as [NSNumber]
        }
    }
    

    Instantiate with:

    let gradient = EdgeGradientView(placement: .top, distance: 100, color: .black)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search