加载后具有不同大小的 UIButton

UIButton with a different size after is load

您好,我想在 UIButton 中添加渐变背景。这是我的方法,但对于 iPhone 7 plus 或 8 plus 它不会覆盖所有按钮。当看到 uibutton 框架 (174.5, 0.0, 164.5, 47.0) 但加载后我可以看到它是 (194.5, 0.0, 184.5, 47.0)。看起来像这样

func setRedGradiant(){
    self.layer.shadowOffset = CGSize.zero
    self.layer.shadowColor = UIColor(red:0, green:0, blue:0, alpha:0.5).cgColor
    self.layer.shadowOpacity = 1
    self.layer.shadowRadius = 4
    let gradient = CAGradientLayer()
    print(self.frame)
    gradient.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
    gradient.colors = [
        UIColor(red:0.97, green:0.34, blue:0.39, alpha:1).cgColor,
        UIColor(red:0.94, green:0.17, blue:0.2, alpha:1).cgColor
    ]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 0.5, y: 0)
    gradient.endPoint = CGPoint(x: 0.5, y: 1)
    gradient.cornerRadius = self.frame.size.height / 2
    self.layer.addSublayer(gradient)
}



@IBOutlet weak var signInButton: UIButton!{
        didSet{
            signInButton.setRedGradiant()
        }
    }

设置 @IBOutlet 后,view 没有正确的框架。我建议你多了解一下 UIViewController lifecycle 来理解这个问题。

您的正确解决方案是在 viewWillLayoutSubviews 方法上为适当的按钮调用 setRedGradiant

每次更改视图边界时都会调用此 method

按钮的尺寸确定后需要设置渐变的边框。一种方便的方法是创建 UIButton 的子类并覆盖 layoutSubviews 以设置渐变。

layoutSubviews() 将在按钮框架更改时调用,但您只想在第一次设置渐变。使用 属性 存储渐变,以便您可以在以后的调用中更新 frame

class GradientButton: UIButton {

    var gradient: CAGradientLayer?

    override func layoutSubviews() {
        super.layoutSubviews()
        setRedGradient()
    }

    func setRedGradient() {
        if gradient == nil {
            self.layer.shadowOffset = CGSize.zero
            self.layer.shadowColor = UIColor(red:0, green:0, blue:0, alpha:0.5).cgColor
            self.layer.shadowOpacity = 1
            self.layer.shadowRadius = 4
            self.gradient = CAGradientLayer()

            self.gradient?.colors = [
                UIColor(red:0.97, green:0.34, blue:0.39, alpha:1).cgColor,
                UIColor(red:0.94, green:0.17, blue:0.2, alpha:1).cgColor
            ]
            self.gradient?.locations = [0, 1]
            self.gradient?.startPoint = CGPoint(x: 0.5, y: 0)
            self.gradient?.endPoint = CGPoint(x: 0.5, y: 1)

            self.layer.addSublayer(self.gradient!)
        }

        // Always update the frame, even if this isn't the first call
        self.gradient?.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
        self.gradient?.cornerRadius = self.frame.size.height / 2
    }
}

要在 Storyboard 中使用它,请在 Identity Inspector 中将 UIButtonclass 更改为 GradientButton

您的出口变为:

@IBOutlet weak var signInButton: GradientButton!

这样做的好处是按钮可以设置和更新自己的渐变,如果您有两个或更多按钮,这会很好。

未来的改进是将颜色设为 属性,这样您就可以拥有更多的按钮,而不仅仅是红色按钮。

我想你应该在 viewDidLoad 处调用 signInButton.setRedGradiant(),并且在函数处使用 .bounds 而不是 .frame

func setRedGradiant(){
    self.layer.shadowOffset = CGSize.zero
    self.layer.shadowColor = UIColor(red:0, green:0, blue:0, alpha:0.5).cgColor
    self.layer.shadowOpacity = 1
    self.layer.shadowRadius = 4
    let gradient = CAGradientLayer()
    print(self.bounds)
    gradient.frame = CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height)
    gradient.colors = [
        UIColor(red:0.97, green:0.34, blue:0.39, alpha:1).cgColor,
        UIColor(red:0.94, green:0.17, blue:0.2, alpha:1).cgColor
    ]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 0.5, y: 0)
    gradient.endPoint = CGPoint(x: 0.5, y: 1)
    gradient.cornerRadius = self.bounds.size.height / 2
    self.layer.addSublayer(gradient)
}