【问题标题】:UIButton with a different size after is load加载后大小不同的 UIButton
【发布时间】:2018-02-27 12:22:15
【问题描述】:

您好,我正在尝试在 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()
        }
    }

【问题讨论】:

  • 你在 viewDidLoad 中调用 setRedGradiant 吗?如果是这样,那么它肯定会显示故事板的框架。

标签: ios swift uibutton gradient


【解决方案1】:

当你的@IBOutlet 被设置时,view 没有正确的框架。建议大家多了解UIViewController lifecycle来理解这个问题。

您的正确解决方案是调用setRedGradiant 以获取viewWillLayoutSubviews 方法上的相应按钮。

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

【讨论】:

  • 谢谢解决问题!!有什么方法可以调用 IBOutlet 中的方法吗?只为代码顺序
  • 您可以使用您的屏幕尺寸计算预期的按钮尺寸。为此请致电UIScreen.main.bounds。
【解决方案2】:

渐变的边框需要在按钮大小确定后设置。一种方便的方法是创建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 中将 UIButton 的 class 更改为 GradientButton。

你的出口变成:

@IBOutlet weak var signInButton: GradientButton!

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

未来的改进是让颜色成为一种属性,这样您就可以拥有更多的红色按钮。

【讨论】:

    【解决方案3】:

    我猜你应该在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)
    }
    

    【讨论】:

    • 我之前尝试过使用边界。我认为唯一的选择是在 viewWillLayoutSubViews 中调用它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    相关资源
    最近更新 更多