Reputation: 634
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
Upvotes: 0
Views: 457
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):
From the top menu bar, select Editor -> Refresh All Views
(or have Automatically Refresh Views
checked). You should see this:
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