简体   繁体   中英

UIButton with a different size after is load

Hi I'm trying to put a gradient background in an UIButton. This is my method but for the iPhone 7 plus or 8 plus it does not cover all the button. 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). 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. I suggest you to learn more about UIViewController lifecycle to understand this problem.

Correct solution for you will be to call setRedGradiant for appropriate button on viewWillLayoutSubviews method.

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.

layoutSubviews() will be called anytime the frame of the button changes, but you'll only want to set up the gradient the first time. Use a property to store the gradient so that you can update the frame on later calls.

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 .

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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