首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >AutoLayout按钮,渐变,不会调整到高度

AutoLayout按钮,渐变,不会调整到高度
EN

Stack Overflow用户
提问于 2019-05-28 00:50:10
回答 2查看 37关注 0票数 0

我想调整每个按钮的高度以适应屏幕的大小。为此,我创建了以下类,其中还包含我之前创建的渐变和阴影路径:

代码语言:javascript
复制
extension UIButton {

    func typeMain() {
        self.translatesAutoresizingMaskIntoConstraints = false
        let height = UIScreen.main.bounds.height * 0.07
        self.heightAnchor.constraint(equalToConstant: height).isActive = true

        self.addCharacterSpacing()
        self.tintColor = UIColor.white
        let color = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1)
        let sndColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1)

        self.layer.cornerRadius = self.frame.size.height / 5.0

        self.applyGradient(colours: [color, sndColor], locations: [0.0, 1.0])

        let shadowSize : CGFloat = 2.0
        self.layer.shadowColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1).cgColor
        self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        self.layer.shadowOpacity = 0.4
        let shadowPath = UIBezierPath(rect: CGRect(x: -shadowSize / 2,
                                                   y: shadowSize,
                                                   width: self.frame.size.width + shadowSize,
                                                   height: self.frame.size.height + shadowSize))
        self.layer.shadowPath = shadowPath.cgPath
        self.layer.shadowRadius = 5
        self.layer.masksToBounds = false
    }
}

按钮正在被调整到屏幕大小,但是渐变和阴影都不是。我该怎么做?

顺便说一句。故事板集中没有高度限制。

EN

回答 2

Stack Overflow用户

发布于 2019-05-28 01:23:05

子类UIButton并重写layoutSubviews以设置layer.shadowPath,这将确保您的阴影边界与视图边界匹配

代码语言:javascript
复制
class CustomButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        let shadowSize: CGFloat = 2.0
        let shadowRect = CGRect(x: -shadowSize / 2,
                                y: shadowSize,
                                width: self.bounds.width + shadowSize,
                                height: self.bounds.height + shadowSize)
        self.layer.shadowPath = UIBezierPath(rect: shadowRect).cgPath        
    }

}

建议

  1. 不将typeMain方法作为UIButton的扩展添加,而是在上面的类中移动它
  2. 简单地保持shadowPath以匹配视图边界,相反,您可以设置

这是最后一个类

代码语言:javascript
复制
class CustomButton: UIButton {

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

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

    override func awakeFromNib() {
        super.awakeFromNib()
        setup()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
    }

    private func setup() {
        self.translatesAutoresizingMaskIntoConstraints = false
        let height = UIScreen.main.bounds.height * 0.07
        self.heightAnchor.constraint(equalToConstant: height).isActive = true

        self.tintColor = UIColor.white

        self.layer.cornerRadius = self.frame.size.height / 5.0
        self.layer.shadowColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1).cgColor
        self.layer.shadowOffset = CGSize(width: -1.0, height: 2.0)
        self.layer.shadowOpacity = 1
        self.layer.shadowRadius = 5
        self.layer.masksToBounds = false
    }

    private func applyGradient(_ rect: CGRect, colors: NSArray, locations: NSArray) {
        guard
            let ctx = UIGraphicsGetCurrentContext(),
            let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors, locations: [0, 0.5])
        else {
            return
        }

        ctx.drawLinearGradient(gradient, start: .zero, end: CGPoint(x: bounds.width, y: 0), options: [])
    }

    override func draw(_ rect: CGRect) {
        let startColor = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1).cgColor
        let endColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1).cgColor
        self.applyGradient(rect, colors: [startColor, endColor], locations: [0.0, 1.0])
    }

}

下面是两个按钮的测试,第一个是UIButton,第二个是子类CustomButton

代码语言:javascript
复制
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton()
        button.setTitle("UIButton", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 16.0, bottom: 0, right: 16.0)
        self.view.addSubview(button)
        button.typeMain()

        let subclassedButton = CustomButton()
        subclassedButton.setTitle("UIButton Subclassed", for: .normal)
        subclassedButton.setTitleColor(.black, for: .normal)
        subclassedButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 16.0, bottom: 0, right: 16.0)
        self.view.addSubview(subclassedButton)

        let salGuide = self.view.safeAreaLayoutGuide
        button.leadingAnchor.constraint(equalTo: salGuide.leadingAnchor, constant: 20.0).isActive = true
        button.topAnchor.constraint(equalTo: salGuide.topAnchor, constant: 20.0).isActive = true

        subclassedButton.leadingAnchor.constraint(equalTo: salGuide.leadingAnchor, constant: 20.0).isActive = true
        subclassedButton.topAnchor.constraint(equalTo: button.bottomAnchor, constant: 20.0).isActive = true
    }

}

这就产生了

票数 1
EN

Stack Overflow用户

发布于 2019-05-28 01:37:08

您似乎在此处设置相对于帧大小的阴影路径,而不是您生成的高度约束。

您可以删除以下内容:

代码语言:javascript
复制
let shadowPath = UIBezierPath(rect: CGRect(x: -shadowSize / 2,
                                                   y: shadowSize,
                                                   width: self.frame.size.width + shadowSize,
                                                   height: self.frame.size.height + shadowSize))

阴影应该可以很好地拥抱按钮。如果你想让阴影有你已经布置的路径,你需要根据你设置的约束来设置宽度和高度(即UIScreen.main.bounds.height * 0.07)。

如果将translatesAutoresizingMaskIntoConstraints设置为false,则将不再相对于传递给对象的任何CGRect帧生成约束。它们是基于锚点和内容大小生成的(在这里,您的高度由锚点显式设置,但您的宽度仍受按钮的内容大小的限制)。换句话说,self.frame在这里是无关紧要的。

如果你这样设置它,它将会工作:

代码语言:javascript
复制
self.widthAnchor.constraint(equalToConstant: self.frame.width).isActive = true
let shadowPath = UIBezierPath(rect: CGRect(x: -shadowSize / 2,
                                       y: shadowSize,
                                       width: self.frame.width + shadowSize,
                                       height: height + shadowSize))

这有帮助吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56329837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档