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)
}
CodePudding user response:
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)
}
CodePudding user response:
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)