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.boundsgradientLayerBottom.frame = bottomBackground.bounds 在我们拥有的代码中并且有效。问题出在渐变层框架上。 我仍然想知道为什么它适用于顶部而不是底部。顺便说一句,忘记在 awakeFromNib 上调用它,所以我不需要调用 didLayout 变量。好提醒 @VictorSanchez 您是通过情节提要还是以编程方式设置约束? 两个都试过了,看是否解决了问题,最终离开了故事板。 @VictorSanchez 我认为您遇到了约束问题,因为我尝试了相同的方法,就像您应用两种不同的渐变来查看 UICollectionViewCell 内部一样,它与我的回答配合得很好。您还可以在我的更新答案中看到输出图像。

以上是关于UICollectionViewCell - 将不同的 CAGradientLayer 应用于不同的 UIView的主要内容,如果未能解决你的问题,请参考以下文章

在 UICollectionViewCell 中添加模糊

UICollectionViewCell与UIScrollView取消didSelectItemAtIndexPath

UICollectionViewCell 子类问题

重用 UICollectionViewCell

UICollectionViewCell 中的 Outlet 为零

UICollectionViewCell 边框/阴影