【问题标题】:Gradient from UIView after orientation transition方向转换后来自 UIView 的渐变
【发布时间】:2020-03-09 16:36:32
【问题描述】:

我有一个 UIView 的扩展来应用渐变:

    extension UIView {

    func applyGradient(colors: [CGColor]) {

        self.backgroundColor = nil
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = self.bounds // Here new gradientLayer should get actual UIView bounds
        gradientLayer.cornerRadius = self.layer.cornerRadius
        gradientLayer.colors = colors
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
        gradientLayer.masksToBounds = true

        self.layer.insertSublayer(gradientLayer, at: 0)
    }
}

在我的 UIView 子类中,我正在创建所有视图并设置约束:

private let btnSignIn: UIButton = {
    let btnSignIn = UIButton()

    btnSignIn.setTitle("Sing In", for: .normal)
    btnSignIn.titleLabel?.font = UIFont(name: "Avenir Medium", size: 35)

    btnSignIn.layer.cornerRadius = 30
    btnSignIn.clipsToBounds = true
    btnSignIn.translatesAutoresizingMaskIntoConstraints = false

    return btnSignIn
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    addSubViews()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    addSubViews()
}

func addSubViews() {
    self.addSubview(imageView)
    self.addSubview(btnSignIn)
    self.addSubview(signUpstackView)
    self.addSubview(textFieldsStackView)
    setConstraints()
}

我已经覆盖了 layoutSubviews 函数,每次更改视图边界时都会调用该函数(包括方向转换),我正在调用 applyGradient。

override func layoutSubviews() {
    super.layoutSubviews()
    btnSignIn.applyGradient(colors: [Colors.ViewTopGradient, Colors.ViewBottomGradient])
}

问题在于,由于某种原因,方向转换梯度应用错误后...

请看截图

我在这里错过了什么?

【问题讨论】:

    标签: ios swift autolayout ios-autolayout


    【解决方案1】:

    如果您查看按钮,您会看到两个渐变。那是因为layoutSubviews 至少被调用了两次,第一次是在第一次呈现视图时,另一次是在方向改变之后。所以你至少添加了两个渐变层。

    你想改变这个,所以你只insertSublayer一次(例如,当视图被实例化时),因为layoutSubviews可以被多次调用,它应该限制自己只调整现有层,而不是添加任何层。

    您也可以只使用layerClass类属性将按钮的主图层设为渐变,然后您完全不必手动调整图层框架:

    @IBDesignable
    public class RoundedGradientButton: UIButton {
    
        static public override var layerClass: AnyClass { CAGradientLayer.self }
        private var gradientLayer: CAGradientLayer      { layer as! CAGradientLayer }
    
        @IBInspectable var startColor: UIColor = .blue  { didSet { updateColors() } }
        @IBInspectable var endColor: UIColor = .red     { didSet { updateColors() } }
    
        override public init(frame: CGRect = .zero) {
            super.init(frame: frame)
            configure()
        }
    
        required public init?(coder: NSCoder) {
            super.init(coder: coder)
            configure()
        }
    
        override public func layoutSubviews() {
            super.layoutSubviews()
            layer.cornerRadius = min(bounds.height, bounds.width) / 2
        }
    }
    
    private extension RoundedGradientButton {
        func configure() {
            gradientLayer.startPoint = CGPoint(x: 0, y: 0)
            gradientLayer.endPoint = CGPoint(x: 1, y: 1)
            updateColors()
    
            titleLabel?.font = UIFont(name: "Avenir Medium", size: 35)
        }
    
        func updateColors() {
            gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
        }
    }
    

    这种技术消除了手动调整图层的frame 的需要,并且还可以产生更好的中间动画再现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 2013-04-05
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多