【问题标题】:Adding a gradient layer to a table view cell element dependant on the cell index path根据单元格索引路径向表格视图单元格元素添加渐变层
【发布时间】:2019-09-30 11:14:22
【问题描述】:

我在将渐变层作为背景添加到表格视图单元格内的元素时遇到了困难。梯度层取决于单元索引路径。我有一个颜色的enum,它使用indexPath 作为它的rawValue。所需的输出很简单,例如 this

这是创建渐变层的函数。我用这个tutorial来写函数。

func setGradientBackground(colorOne: UIColor, colorTwo: UIColor, name: String) {
    let gradient = CAGradientLayer()
    gradient.frame = bounds
    gradient.colors = [colorOne.cgColor, colorTwo.cgColor]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 1, y: 1)
    gradient.endPoint = CGPoint(x: 0, y: 0)
    gradient.name = name
    layer.insertSublayer(gradient, at: 0)
}

为表格视图单元格中的元素添加渐变已经尝试了几件事。目前我正在循环可见单元格以添加图层。我试过从viewWillLayoutSubviews 打电话。这是我唯一一次看到应用了渐变。

我看到了两个问题。该应用程序变得无法使用,因为我认为当视图上的某些内容发生变化时,此函数或多或少会被连续调用。并且图层被绘制在单元格中的所有其他内容上。

func configTableCells() {
    guard let cells = self.tableView.visibleCells as? [GroupTableCell] else {return}
    for (i, cell) in cells.enumerated() {
        if shouldAddSubLayer(cell) {
            guard let colorOne = Colors(rawValue: i)?.classicColor,
                let colorTwo = Colors(rawValue: i)?.alternativeColor else {continue}
            cell.taskInfoCollectionView.setGradientBackground(colorOne: colorOne,
                                                              colorTwo: colorTwo,
                                                              name: cellLayerName)
        }
    }
}

我尝试在cellForRowAtwillDisplay Cell 中添加图层,但这不起作用。我相信这是因为细胞还没有“存在”,所以添加一层没有区别。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: groupCellId, for: indexPath) as! GroupTableCell
    cell.groupNameLabel.text = "Group Name"
    cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
    if shouldAddSubLayer(cell) {
        if let colorOne = Colors(rawValue: indexPath.row)?.classicColor,
            let colorTwo = Colors(rawValue: indexPath.row)?.alternativeColor {
        cell.taskInfoCollectionView.setGradientBackground(colorOne: colorOne,
                                                          colorTwo: colorTwo,
                                                          name: cellLayerName)
        }
    }
    return cell
} 

我还包含了这个函数,因为我阅读了另一个 stackOverflow 问题,我应该检查单元格是否已经有层以避免不断添加它。 (我无法链接问题,因为我现在找不到)

func shouldAddSubLayer(_ cell: GroupTableCell) -> Bool {
    guard let sublayers = cell.layer.sublayers else {return true}
    return sublayers.filter({ $0.name == cellLayerName }).count == 0
}

任何有关如何获得此工作欢迎的建议,谢谢。

【问题讨论】:

    标签: ios swift uitableview gradient


    【解决方案1】:

    试试VisualEffect

    在您的ViewDidLoad()中添加以下代码

    if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    tableView.backgroundColor = UIColor.clear
    let blurEffect = UIBlurEffect(style: .light)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    tableView.backgroundView = blurEffectView
    
    //if inside a popover
    if let popover = navigationController?.popoverPresentationController {
        popover.backgroundColor = UIColor.clear
    }
    
    //if you want translucent vibrant table view separator lines
    tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)}
    

    【讨论】:

    • 感谢本,需要进行一些修改,但似乎可以正常工作,谢谢!
    【解决方案2】:

    对于任何可能觉得这很有用的人,让它工作所需的更改..

    使用 Ben 建议的视觉效果,我能够做到这一点。我从来没有使用过视觉效果,所以不确定它为什么会起作用。同样,我可能需要一些改进

    在自定义表格单元格类中,我添加了UIVisualEffectView。在其内容视图中,我添加了我想要更改其背景的元素。

    将任何子视图添加到视觉效果视图的 contentView 属性中。 不要将子视图直接添加到视觉效果视图本身

    lazy var visualEffectView: UIVisualEffectView = {
        let v = UIVisualEffectView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.contentView.addSubview(taskInfoCollectionView)
        NSLayoutConstraint.activate([
            taskInfoCollectionView.topAnchor.constraint(equalTo: v.topAnchor),
            taskInfoCollectionView.leadingAnchor.constraint(equalTo: v.leadingAnchor),
            taskInfoCollectionView.trailingAnchor.constraint(equalTo: v.trailingAnchor),
            taskInfoCollectionView.bottomAnchor.constraint(equalTo: v.bottomAnchor),
        ])
        return v
    }()
    

    回到控制器中,我使用此功能将渐变添加到采用索引和单元格的视觉效果视图

    func addGradient(_ i: Int, _ cell: GroupTableCell) {
        guard let colorOne = Colors(rawValue: i)?.classicColor,
            let colorTwo = Colors(rawValue: i)?.alternativeColor else {return}
        cell.visualEffectView.contentView.setGradientBackground(colorOne: colorOne,
                                                          colorTwo: colorTwo,
                                                          name: cellLayerName)
    }
    

    我仍然需要向viewWillLayoutSubviews 添加一个函数。这是为了配置cellForRowAt 没有的单元格。 setGradients 属性最初设置为 true,但随后立即设置为 false,因此不会像以前那样连续调用它。

    var setGradients = true    
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        if setGradients {
            configTableCells()
            setGradients = false
        }
    }
    
    func configTableCells() {
        guard let cells = self.tableView.visibleCells as? [GroupTableCell] else {return}
        for (i, cell) in cells.enumerated() {
            if shouldAddSubLayer(cell) {
                addGradient(i, cell)
            }
        }
    }
    

    然后终于在cellForRowAt 这似乎处理了其余的事情,一切似乎都运行顺利,没有延迟。

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: GROUP_CELL_ID, for: indexPath) as! GroupTableCell
        cell.groupNameLabel.text = "Group Name"
        cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
        addGradient(indexPath.row, cell)
        return cell
    }
    

    我尝试使用UIView,而不是UIVisualEffectView。但渐变再次覆盖单元格内容。所以需要UIVisualEffectView

    【讨论】:

      猜你喜欢
      • 2014-10-22
      • 2021-10-09
      • 2011-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      相关资源
      最近更新 更多