渐变保持在集合视图中的单元格之间快速切换

Posted

技术标签:

【中文标题】渐变保持在集合视图中的单元格之间快速切换【英文标题】:gradient keeps switching between cells in collection view in swift 【发布时间】:2018-12-03 15:25:46 【问题描述】:

我的收藏视图单元格有一个渐变背景,每个渐变都不同,具体取决于单元格的标签(例如圣诞节是紫色渐变,生日是绿色渐变)但是当滚动浏览收藏视图时,渐变会保持关于改变细胞。有没有办法解决这个问题?

这是我用来将渐变设置为背景视图的代码。它在cellForItemAt

cell.mainView.setGradientBackground(colours: self.getColourFromTag(tag: self.lists[indexPath.item].tag))

.setGradientBackground 是 UIView 的扩展,它只是为背景设置渐变。此处显示:

func setGradientBackground(colours: [CGColor]) 

    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = bounds
    gradientLayer.colors = colours
    gradientLayer.locations = [0.0, 1.0]
    gradientLayer.startPoint = CGPoint(x: 1.0, y: 1.0)
    gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
    layer.insertSublayer(gradientLayer, at: 0)

我使用下面的方法来获取渐变中的颜色

func getColourFromTag(tag: String) -> [CGColor] 

    if tag == "Christmas" 

        return [Colours.gradients.festive.start.cgColor, Colours.gradients.festive.end.cgColor]

    else if tag == "Birthday" 

        return [Colours.gradients.lime.start.cgColor, Colours.gradients.lime.end.cgColor]

    else if tag == "Valentines Day" 

        return [Colours.gradients.strawberry.start.cgColor, Colours.gradients.strawberry.end.cgColor]

    else if tag == "Charity" 

        return [Colours.gradients.blueberry.start.cgColor, Colours.gradients.blueberry.end.cgColor]

    else if tag == "Event" 

        return [Colours.gradients.fire.start.cgColor, Colours.gradients.fire.end.cgColor]

    else
        return [Colours.gradients.midnight.start.cgColor, Colours.gradients.midnight.end.cgColor]
    

我尝试将每个 [color] 附加到一个数组中,然后将其放入 .setGradientBackgroundindexPath.item 中,如下所示:

var colours = [[CGColor]]()

colours[indexPath.item] = self.getColourFromTag(tag: self.lists[indexPath.item].tag)
cell.mainView.setGradientBackground(colours: colours[indexPath.item])

但是,这不起作用,因为它超出了范围。有没有人有办法解决吗?谢谢。

【问题讨论】:

setGradientBackground() 是什么意思? 我已编辑问题以显示该代码:) 细胞被重复使用,你每次都这样做layer.insertSublayer(gradientLayer, at: 0)。因此,通过重用,如果单元格有前一层,它将是:0 处的层:新渐变,1 处的层:前一层等。如果发现为CAGradientLayer,则删除前一层 感谢您的回复,我该怎么做呢? (如果找到则删除图层) layer.sublayers.filter(where: $0 as? CAGradient).forEach$0.removeFromSuperlayer? 【参考方案1】:

阅读setGradientBackground() 中的代码,您总是会初始化一个新的CAGradientLayer 并将其插入到单元格的最低位置。每次再次调用 setGradientBackground() 时,新的渐变层将位于您已插入的所有其他渐变之下。

尝试从子层中获取已经存在的CAGradientLayer 并设置新颜色。

    var gradientLayer = CAGradientLayer()
    if let sublayers = layer.sublayers 
        for sublayer in sublayers 
            if let gLayer = sublayer as? CAGradientLayer 
                gradientLayer = gLayer
                break
            
        
    
    gradientLayer.frame = bounds
    gradientLayer.colors = colours
    gradientLayer.locations = [0.0, 1.0]
    gradientLayer.startPoint = CGPoint(x: 1.0, y: 1.0)
    gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
    layer.insertSublayer(gradientLayer, at: 0)

编辑

这是一个更类似于 Swift 的版本 (Swift 4.2),使用 compactMap() 获取 layer.sublayers 中的第一个现有渐变层:

if let existingLayer = (layer.sublayers?.compactMap  $0 as? CAGradientLayer )?.first 
    gradientLayer = existingLayer

【讨论】:

我出于不同的原因使用它。我用它来检查图层是否是子图层并且效果很好,谢谢 非常感谢这个惊人的解决方案! :D

以上是关于渐变保持在集合视图中的单元格之间快速切换的主要内容,如果未能解决你的问题,请参考以下文章

在“集合视图”单元格中的UIView上设置渐变背景

表格单元格中的集合视图。这是重用的错误

iOS:自适应集合视图单元格宽度

呈现和关闭模式视图控制器时如何保持选择集合视图单元格?

表格视图中单元格之间的快速距离[关闭]

在集合视图单元格中自行调整图像大小