渐变层覆盖集合视图中的所有项目,不考虑间距
Gradient Layer covers all items in Collection View with no respect of spacing
所以我使用了一个名为 Scaling Carousel 的第三方库,大部分情况下它都非常好,但出于某种原因,当我尝试自定义它并向其添加渐变图层甚至添加阴影时没有贴好?我在下面附上了一张图片以供参考。
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
}
这是缩放轮播代码
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
我的建议是使用一个 UIView
subclass,其中包含渐变和圆角半径逻辑。
因此,首先,将此代码添加到您的项目中:
@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
}
}
接下来,为了进行快速测试,将视图控制器添加到故事板并添加 UIView
子视图。将该视图的 class 更改为 KFGradientView
(忽略 scratchy -- 你应该在那里看到你的项目名称):
在顶部菜单栏中,select Editor -> Refresh All Views
(或选中 Automatically Refresh Views
)。你应该看到这个:
假设您这样做,请转到您的 Collection View Cell 原型,并将 mainView
的 class 从 UIView
更改为 KFGradientView
。你应该看到同样的事情发生在那里。
然后,从 class ScalingCarouselCell: UICollectionViewCell
中的 func scale(...)
中删除这一行:
mainView.layer.cornerRadius = 28
并将您的 cellForItemAt
函数更改为:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ScalingCarouselCell
return cell
}
至于您的 mainView
没有正确调整大小/在单元格中的位置,那么,这是一个完全不同的问题。如果你不明白,post 那是一个新问题。
所以我使用了一个名为 Scaling Carousel 的第三方库,大部分情况下它都非常好,但出于某种原因,当我尝试自定义它并向其添加渐变图层甚至添加阴影时没有贴好?我在下面附上了一张图片以供参考。
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
}
这是缩放轮播代码
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
我的建议是使用一个 UIView
subclass,其中包含渐变和圆角半径逻辑。
因此,首先,将此代码添加到您的项目中:
@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
}
}
接下来,为了进行快速测试,将视图控制器添加到故事板并添加 UIView
子视图。将该视图的 class 更改为 KFGradientView
(忽略 scratchy -- 你应该在那里看到你的项目名称):
在顶部菜单栏中,select Editor -> Refresh All Views
(或选中 Automatically Refresh Views
)。你应该看到这个:
假设您这样做,请转到您的 Collection View Cell 原型,并将 mainView
的 class 从 UIView
更改为 KFGradientView
。你应该看到同样的事情发生在那里。
然后,从 class ScalingCarouselCell: UICollectionViewCell
中的 func scale(...)
中删除这一行:
mainView.layer.cornerRadius = 28
并将您的 cellForItemAt
函数更改为:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ScalingCarouselCell
return cell
}
至于您的 mainView
没有正确调整大小/在单元格中的位置,那么,这是一个完全不同的问题。如果你不明白,post 那是一个新问题。