【问题标题】:horizontal gradient doesn't work on dynamic width content水平渐变不适用于动态宽度内容
【发布时间】:2018-11-09 06:19:55
【问题描述】:

我正在尝试根据要求为按钮或视图实现渐变。但是每当我尝试为宽度是动态的按钮/视图(对于水平渐变)这样做时,它只会加载一半。

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,它会完美加载两个视图/按钮。任何帮助表示赞赏。

【问题讨论】:

    标签: ios swift uiview uibutton gradient


    【解决方案1】:
    <gradientlayer>.layoutIfNeeded()
    

    在计算完动态组件的宽度后调用此方法。

    【讨论】:

      【解决方案2】:

      UIView.layer 中的所有子图层在更改超级图层时不会自动更改其大小。覆盖UIView.layoutSubviews() 的方法并从UIView.layer 更新边界CAGradientLayer。

      【讨论】:

        【解决方案3】:

        当您应用渐变时,按钮的框架很可能与稍后的不同。您可以尝试在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
        }
        

        既然已经完成,您应该尝试覆盖另外 2 个方法来修复框架:

        override func layoutSubviews() {
            super.layoutSubviews()
            refreshGradientLayer()
        }
        override var frame: CGRect {
            didSet {
                refreshGradientLayer()
            }
        }
        private func refreshGradientLayer() {
            currentGradientLayer?.frame = bounds
        }
        

        这无论如何都会刷新渐变; layoutSubviews 将在您的视图是带有约束的布局时被调用,frame 在以编程方式完成时被调用。

        【讨论】:

          猜你喜欢
          • 2012-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-24
          • 2016-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多