UICollectionViewCell - 将不同的 CAGradientLayer 应用于不同的 UIView
Posted
技术标签:
【中文标题】UICollectionViewCell - 将不同的 CAGradientLayer 应用于不同的 UIView【英文标题】:UICollectionViewCell - Applying different CAGradientLayer to different UIView 【发布时间】:2019-05-31 06:45:56 【问题描述】:TL;DR:有 2 个需要 CAGradientLayer 的视图(顶部和底部)。意外的行为是只有顶视图显示渐变。底部不显示渐变。
在我们的应用程序中,我有一个具有 UICollectionView 的视图,如图所示:
对于每个 UICollectionViewCell,我创建了一个自定义类来执行布局细节。在 UICollectionViewCell 上,我有一个“topBackground”和“bottomBackground”,它们是包含每个单元格信息的标签的视图:
@IBOutlet weak var topBackground: UIView!
@IBOutlet weak var bottomBackground: UIView!
顶视图和底视图、标签显示正确且约束正常工作。
我们决定在顶视图和底视图上添加渐变效果(请参阅图像的详细信息,顶部渐变标记为红色,底部细节标记为黄色)。
对于代码,我们使用了以下内容:
override func layoutSubviews()
if !didLayout
// Top View
let gradientLayer: CAGradientLayer = CAGradientLayer()
gradientLayer.frame = topBackground.frame
gradientLayer.colors =
[UIColor.black.withAlphaComponent(0.5).cgColor, UIColor.black.withAlphaComponent(0).cgColor]
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.9)
topBackground.layer.insertSublayer(gradientLayer, at: 0)
topBackground.backgroundColor = .clear
topBackground.alpha = 0.5
// Bottom View
let gradientLayerBottom: CAGradientLayer = CAGradientLayer()
gradientLayerBottom.frame = bottomBackground.frame
gradientLayerBottom.colors =
[UIColor.black.withAlphaComponent(0.5).cgColor, UIColor.black.withAlphaComponent(0).cgColor]
gradientLayerBottom.startPoint = CGPoint(x: 0.5, y: 0.9)
gradientLayerBottom.endPoint = CGPoint(x: 0.5, y: 0)
bottomBackground.layer.insertSublayer(gradientLayerBottom, at: 0)
bottomBackground.backgroundColor = .clear
bottomBackground.alpha = 0.5
didLayout = true
else
print("already performed layout")
变量didLayout
是为了避免在collection view滚动时多个渐变重叠。
结果:
-
顶视图正在显示渐变(预期)。
底视图未显示渐变(意外)。
我们知道底部视图存在约束条件,因为如果我们将颜色更改为 .clear
以外的颜色,它会显示另一种颜色。只是gradientLayerBottom
没有显示。
关于如何让gradientLayerBottom
显示的任何想法?
【问题讨论】:
你为什么要在0
插入子层?
@Lu_ 试图确保它位于layer.sublayers
的第一个位置。还尝试了addSublayer
,而不是insertSublayer(at:)
,但结果相同。
如果你设置了与顶部渐变层相同的起点和终点?很奇怪,代码看起来还可以
@Lu_ 如果我设置相同的起点和终点,同样的结果,底部的不显示。
【参考方案1】:
试试这个
extension UIView
func setGradientBackgroundImage(colorTop: UIColor, colorBottom: UIColor)
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorTop.cgColor, colorBottom.cgColor]
gradientLayer.frame = bounds
layer.insertSublayer(gradientLayer, at: 0)
放入UICollectionViewCell类
class CollVwCell : UICollectionViewCell
@IBOutlet weak var VwTop: UIView!
@IBOutlet weak var VwBottom: UIView!
override func awakeFromNib()
super.awakeFromNib()
DispatchQueue.main.async
self.VwTop.setGradientBackgroundImage(colorTop: UIColor.red, colorBottom: UIColor.white)
self.VwBottom.setGradientBackgroundImage(colorTop: UIColor.white, colorBottom: UIColor.purple)
输出:
【讨论】:
嗯,那个 gradientLayer.frame = bounds 做到了!我做到了:gradientLayer.frame = topBackground.bounds
和 gradientLayerBottom.frame = bottomBackground.bounds
在我们拥有的代码中并且有效。问题出在渐变层框架上。
我仍然想知道为什么它适用于顶部而不是底部。顺便说一句,忘记在 awakeFromNib 上调用它,所以我不需要调用 didLayout 变量。好提醒
@VictorSanchez 您是通过情节提要还是以编程方式设置约束?
两个都试过了,看是否解决了问题,最终离开了故事板。
@VictorSanchez 我认为您遇到了约束问题,因为我尝试了相同的方法,就像您应用两种不同的渐变来查看 UICollectionViewCell 内部一样,它与我的回答配合得很好。您还可以在我的更新答案中看到输出图像。以上是关于UICollectionViewCell - 将不同的 CAGradientLayer 应用于不同的 UIView的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionViewCell与UIScrollView取消didSelectItemAtIndexPath