显示 UITableViewCell 时,CAGradientLayer 无法正确调整大小

CAGradientLayer not resizing correctly when UITableViewCell is shown

我正在开发一个在 tableViewCell 中显示头像图片和一些个人资料信息的应用程序。同样的头像图片设置为单元格背景,然后我在它上面有另一个带有渐变的UIView,它是使用CAGradientLayer创建的。

问题是,当我的单元格显示时,渐变没有正确的框架大小(应该是单元格的大小),而是在右边留下一个空 space。当我滚动 tableView 时,渐变会正确调整大小。

这是我创建渐变的方法:

func awakeFromNib() {
    let startColor = UIColor.gradientOverlay.cgColor //Defined elsewhere
    let endColor = UIColor.black.cgColor

    gradientLayer.frame = gradientView.frame
    gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
    gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
    gradientLayer.colors = [startColor, endColor]
    self.gradientView.layer.addSublayer(gradientLayer)
}

此外,我已经重写了 layoutSubviews 方法,如下所示:

override func layoutSubviews() {
    super.layoutSubviews()

    gradientLayer.frame = gradientView.frame
    self.layoutIfNeeded()
}

呈现视图时的屏幕如下所示(我已删除敏感信息):

请注意,在右侧的标签之后,颜色发生了变化。最后一列颜色只是模拟器屏幕的边框。

你们知道如何解决这个问题吗?

编辑:更正了标题上的拼写错误。

渐变原生使用 CAGradientLayerCALayer 而不是 UIView。所以视图布局不会影响它。

自定义class

你可以用这个class我写的:

class GradientView: UIView {

    var colors: [UIColor]? { didSet { syncColors() } }

    var direction: GradientDirection = .topToBottom {
        didSet {
            layer.startPoint = direction.startPoint
            layer.endPoint = direction.endPoint
        }
    }

    enum GradientDirection {
        case rightToLeft
        case leftToRight
        case bottomToTop
        case topToBottom
        case custom(startPoint: CGPoint,endPoint: CGPoint)

        var startPoint: CGPoint {
            switch self {
            case .rightToLeft: return CGPoint(x: 1, y: 0)
            case .leftToRight: return .zero
            case .bottomToTop: return CGPoint(x: 0, y: 1)
            case .topToBottom: return .zero
            case .custom(let startPoint, _): return startPoint
            }
        }

        var endPoint: CGPoint {
            switch self {
            case .rightToLeft: return .zero
            case .leftToRight: return CGPoint(x: 1, y: 0)
            case .bottomToTop: return .zero
            case .topToBottom: return CGPoint(x: 0, y: 1)
            case .custom(_, let endPoint): return endPoint
            }
        }

        static var interfaceDirection: GradientDirection {
            switch UIApplication.shared.userInterfaceLayoutDirection {
            case .leftToRight: return .leftToRight
            case .rightToLeft: return .rightToLeft
            }
        }
    }

    override class var layerClass: AnyClass { return CAGradientLayer.self }

    override var layer: CAGradientLayer { return super.layer as! CAGradientLayer }

    override func layoutSubviews() { syncColors() }

    private func syncColors() { layer.colors = colors?.map() { [=10=].cgColor } }
}

简化器class

在这个简单的帮助下 class:

enum GradientDirection {
    case rightToLeft
    case leftToRight
    case bottomToTop
    case topToBottom
    case custom(startPoint: CGPoint,endPoint: CGPoint)

    var startPoint: CGPoint {
        switch self {
        case .rightToLeft: return CGPoint(x: 1, y: 0)
        case .leftToRight: return .zero
        case .bottomToTop: return CGPoint(x: 0, y: 1)
        case .topToBottom: return .zero
        case .custom(let startPoint, _): return startPoint
        }
    }

    var endPoint: CGPoint {
        switch self {
        case .rightToLeft: return .zero
        case .leftToRight: return CGPoint(x: 1, y: 0)
        case .bottomToTop: return .zero
        case .topToBottom: return CGPoint(x: 0, y: 1)
        case .custom(_, let endPoint): return endPoint
        }
    }

    static var interfaceDirection: GradientDirection {
        switch UIApplication.shared.userInterfaceLayoutDirection {
        case .leftToRight: return .leftToRight
        case .rightToLeft: return .rightToLeft
        }
    }
}

这样你就有了一个普通视图,它对来自超级视图的任何布局通知做出反应。

用法

只需添加子视图并将 class 设置为 GradientView 并使用自动布局或您想要的任何其他布局进行布局。

或使用代码:

    let gradientView: GradientView = {
        let gradientView = GradientView(frame: self.frame)
        gradientView.colors = [
            UIColor.black.withAlphaComponent(1),
            UIColor.black.withAlphaComponent(0)
        ]
        gradientView.direction = .bottomToTop

        return gradientView
    }()

请注意,如果您希望视图具有一定的透明度,您需要删除视图的原始 backgroundColor

我找到了解决方法。由于问题出在层的宽度上,我使用 UIScreen.main.bounds.width.

初始化了它的宽度