简体   繁体   English

加载后大小不同的UIButton

[英]UIButton with a different size after is load

Hi I'm trying to put a gradient background in an UIButton. 嗨,我正在尝试在UIButton中放置渐变背景。 This is my method but for the iPhone 7 plus or 8 plus it does not cover all the button. 这是我的方法,但是对于iPhone 7 plus或8 plus,它不能覆盖所有按钮。 When a see the uibutton frame (174.5, 0.0, 164.5, 47.0) but after is load I can see that is (194.5, 0.0, 184.5, 47.0). 当看到uibutton框架(174.5、0.0、164.5、47.0)但加载后,我看到的是(194.5、0.0、184.5、47.0)。 It looks like this 看起来像这样 在此处输入图片说明

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()
        }
    }

When your @IBOutlet is set, view doesn't has correct frame. 设置@IBOutletview没有正确的框架。 I suggest you to learn more about UIViewController lifecycle to understand this problem. 我建议您了解有关UIViewController lifecycle更多信息,以了解此问题。

Correct solution for you will be to call setRedGradiant for appropriate button on viewWillLayoutSubviews method. 正确的解决方案是在viewWillLayoutSubviews方法上为相应的按钮调用setRedGradiant

This method is called each time when your view bounds is changed. 每次更改视图范围时都会调用此方法

The gradient's frame needs to be set after the size of the button has been established. 建立按钮的大小后,需要设置渐变的框架。 One handy way to do that is to create a subclass of UIButton and override layoutSubviews to set up the gradient. 一种方便的方法是创建UIButton的子类并重写layoutSubviews来设置渐变。

layoutSubviews() will be called anytime the frame of the button changes, but you'll only want to set up the gradient the first time. 每当按钮的框架更改时,都会调用layoutSubviews() ,但是您只想在第一次设置渐变。 Use a property to store the gradient so that you can update the frame on later calls. 使用属性存储渐变,以便您可以在以后的调用中更新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
    }
}

To use this in the Storyboard, change the class of your UIButton to GradientButton in the Identity Inspector . 要在情节提要中使用此功能,请在Identity Inspector中将UIButtonclass更改为GradientButton

Your outlet becomes: 您的出口将变为:

@IBOutlet weak var signInButton: GradientButton!

The advantage of doing it this way is that the button sets and updates its own gradient which is nice if you have two or more buttons. 这样做的好处是按钮可以设置和更新自己的渐变,如果您有两个或多个按钮,则效果很好。

A future improvement would be to make the colors a property so that you could have more than just red buttons. 未来的改进将是使颜色成为一种属性,这样您不仅可以拥有红色按钮。

I guess you should call signInButton.setRedGradiant() at viewDidLoad , also use .bounds instead of .frame at function: 我想你应该叫signInButton.setRedGradiant()viewDidLoad ,也使用.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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM