我正在尝试根据需要为按钮或视图实现渐变。但是每当我尝试按钮/视图时,宽度是动态的(对于水平渐变),它只加载一半相同。
func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = colours.map { $0.cgColor }
gradient.startPoint = orientation.startPoint
gradient.endPoint = orientation.endPoint
self.layer.insertSublayer(gradient, at: 0)
}
GradientOrientation通过以下代码获得。
enum GradientOrientation {
case topRightBottomLeft
case topLeftBottomRight
case horizontal
case vertical
var startPoint: CGPoint {
return points.startPoint
}
var endPoint: CGPoint {
return points.endPoint
}
var points: GradientPoints {
switch self {
case .topRightBottomLeft:
return (CGPoint.init(x: 0.0, y: 1.0), CGPoint.init(x: 1.0, y: 0.0))
case .topLeftBottomRight:
return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 1, y: 1))
case .horizontal:
return (CGPoint.init(x: 0.0, y: 0.5), CGPoint.init(x: 1.0, y: 0.5))
case .vertical:
return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 0.0, y: 1.0))
}
}
}
但如果宽度为150,它对于视图/按钮都会完美加载。任何帮助表示赞赏。
答案 0 :(得分:1)
如果稍后应用渐变,则按钮的框架很可能不一样。您可以尝试在applyGradient
中打印边界以进行检查。
无论如何你应该添加更多逻辑;因为它看起来像视图的子类,所以存储图层会很棒。目前,如果applyGradient
被调用两次,您会发生什么?你很可能会有2个渐变。
所以你要添加:
private var currentGradientLayer: CAGradientLayer?
func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) {
currentGradientLayer?.removeFromSuperlayer()
currentGradientLayer = nil
let gradient: CAGradientLayer = {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = colours.map { $0.cgColor }
gradient.startPoint = orientation.startPoint
gradient.endPoint = orientation.endPoint
}()
self.layer.insertSublayer(gradient, at: 0)
currentGradientLayer = gradient
}
现在,既然这样做了,你应该尝试覆盖另外两种方法来修复帧:
override func layoutSubviews() {
super.layoutSubviews()
refreshGradientLayer()
}
override var frame: CGRect {
didSet {
refreshGradientLayer()
}
}
private func refreshGradientLayer() {
currentGradientLayer?.frame = bounds
}
这应该在任何情况下刷新渐变;当您的视图是带有约束的布局时,layoutSubviews
将被调用,frame
将以编程方式进行调用。
答案 1 :(得分:0)
更改超级图层时,UIView.layer中的所有子图层都不会自动更改其大小。覆盖UIView.layoutSubviews()
的方法并从UIView.layer更新边界CAGradientLayer。
答案 2 :(得分:0)
<gradientlayer>.layoutIfNeeded()
计算完动态分量的宽度后,调用此方法。