为啥我的渐变子层显示奇怪?

Posted

技术标签:

【中文标题】为啥我的渐变子层显示奇怪?【英文标题】:Why is my gradient sublayer displaying weirdly?为什么我的渐变子层显示奇怪? 【发布时间】:2018-02-16 12:25:22 【问题描述】:

我正在尝试将渐变添加到自定义表格单元格中的视图。但是,它的显示很奇怪,好像它没有从容器中获得正确的 CGRect。

首先,我将标签及其周围的框分别连接到属性标签和标签容器。

我已经定义了一个渐变函数:

func gradient(view: UIView) -> CAGradientLayer 
    let gradient = CAGradientLayer()
    gradient.frame = view.bounds
    gradient.startPoint = CGPoint(x: 0, y: 0.5)
    gradient.endPoint = CGPoint(x: 1, y: 0.5)
    gradient.colors = [
        UIColor.red.cgColor,UIColor.blue.cgColor]
    return gradient

在 cellForRowAt 中,我有:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> ShoppingListCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "customShoppingListCell", for: indexPath) as! ShoppingListCell

    cell.label.text = categories![indexPath.section].items.filter(predicate)[indexPath.row].title

    cell.labelContainer.layer.insertSublayer(gradient(view: cell.labelContainer), at:0)

    cell.selectionStyle = .none

    return cell

但结果表如下所示:

这一切都有点奇怪和不一致。

【问题讨论】:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)方法中移动渐变代码 我已经试过了 【参考方案1】:

你有几个问题...

1) 重复使用单元格 - 每次请求单元格时,您都会添加一个新的子图层。这就是为什么您会在单元格上看到多个渐变层。

2) 图层不会随视图“自动调整大小”,因此您需要在单元格框架更改时更新图层框架。在初始化时,单元格框架还没有(必然)设置。

您可能会发现使用带有“内置”渐变的子类UIView 比在配置单元格时尝试添加它要容易得多。

试试这个...

创建一个将控制渐变的自定义UIView,并将labelContainer 的类设置为该新子类。 (您无需将其设为 IBOutlet,因为您无需在运行时对其进行修改。)

这是一个简单的例子。请注意,通过创建新的UIView 子类@IBDesignable,它也会出现在您的故事板中。

import UIKit

@IBDesignable
class SampleGradientView: UIView 

    override class var layerClass: AnyClass 
        return CAGradientLayer.self
    

    override func layoutSubviews() 
        let gradientLayer = layer as! CAGradientLayer
        gradientLayer.colors = [UIColor.red.cgColor,UIColor.blue.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0)
    



class ShoppingListCell: UITableViewCell 

    @IBOutlet var label: UILabel!



class GradTableCellsTableViewController: UITableViewController 

    var catTitles = [
        "Meat & Fish",
        "Fruit & Veg",
        "Dairy"
    ]

    var catData = [
        ["Steak"],
        ["Apricot", "Asparagus"],
        ["Milk"]
    ]

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.rowHeight = 56.0

    

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int 
        // #warning Incomplete implementation, return the number of sections
        return catTitles.count
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        // #warning Incomplete implementation, return the number of rows
        return catData[section].count
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "customShoppingListCell", for: indexPath) as! ShoppingListCell

        // Configure the cell...
        cell.label.text = catData[indexPath.section][indexPath.row]

        return cell
    


故事板:

结果:

【讨论】:

好的,这对我有用。因此,在之前的答案中,我被告知将代码放在单元格的 layoutSubviews() 中,但这只会深入一层,即它会影响其子层,但不会影响所有后代层。我的理解正确吗? 不确定你在问什么...这是一种使用带有“内置”渐变层的UIView 子类的方法。您是否打算将其他子图层添加到渐变视图? 不,只是想正确理解它。 是否有其他方法可以知道视图何时调整大小? 如果你需要知道它什么时候被调整大小(通常你不需要,如果你正在使用自动布局),那么是的,你想利用layoutSubviews().【参考方案2】:

尝试使用cell.labelContainer.layer.masksToBounds = true 应该会有所帮助

【讨论】:

去掉了下唇,但右边还有那个灰色的缝隙 在 layoutSubviews 中调用这个 cell.labelContainer.layer.insertSublayer(gradient(view: cell.labelContainer), at:0) 发生这种情况是因为尚未计算约束 不改变结果 别忘了调用 super.layoutSubviews()

以上是关于为啥我的渐变子层显示奇怪?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我无法使用具有自动布局的渐变子层来定位我的视图?它没有出现

渐变子层不透明度

为啥我的引导 btn 反转按钮显示为灰色而不是黑色渐变?

为啥这个 SVG 中的渐变显示为黑色?

为啥我的 SVG 径向渐变在基于 Chrome 的浏览器中没有显示,但在 Firefox 中显示?

每次视图出现时,UIView 层的子层显示不同/随机