2017-02-13 58 views
1

您好我有以下代码:添加约束到一个自定义的UIButton不起作用

class MyController {  
    override func viewDidLoad() { 
     self.addButtons() 

     super.viewDidLoad() 
    } 

    func addButtons() { 
     let cancelButton = UIButton(type: .custom) 
     let validateButton = UIButton(type: .custom) 

     cancelButton.setImage(UIImage(named: "cancel_icon"), for: .normal) 
     validateButton.setImage(UIImage(named: "validate_icon"), for: .normal) 

     cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) 
     validateButton.addTarget(self, action: #selector(validateAction), for: .touchUpInside) 

     cancelButton.translatesAutoresizingMaskIntoConstraints = false 
     validateButton.translatesAutoresizingMaskIntoConstraints = false 

     self.view.addSubview(cancelButton) 
     self.view.addSubview(validateButton) 

     let leftCancel = NSLayoutConstraint(item: cancelButton, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 16) 
     let bottomCancel = NSLayoutConstraint(item: cancelButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 20) 
     let widthCancel = NSLayoutConstraint(item: cancelButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightCancel = NSLayoutConstraint(item: cancelButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let rightValidate = NSLayoutConstraint(item: validateButton, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: 16) 
     let bottomValidate = NSLayoutConstraint(item: validateButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 20) 
     let widthValidate = NSLayoutConstraint(item: validateButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightValidate = NSLayoutConstraint(item: validateButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     NSLayoutConstraint.activate([leftCancel, bottomCancel, rightValidate, bottomValidate, widthCancel, heightCancel, widthValidate, heightValidate]) 

     self.view.layoutIfNeeded() 
    } 

    func cancelAction() { 
     self.dismiss(animated: true, completion: nil) 
    } 

    func validateAction() { 
     self.dismiss(animated: true, completion: nil) 
    } 
} 

所以基本上我只是增加了宽度和高度约束两个按钮,我设置cancelButton到左下和validateButton右下。

我的按钮没有出现。当我按照这种方式设置按钮的框架时,它的工作原理如下:

cancelButton.frame = CGRect(x: 16, y: self.view.frame.height - 40, width: 20, height: 20) 
validateButton.frame = CGRect(x: self.view.frame.width - 36, y: self.view.frame.height - 40, width: 20, height: 20) 

有人知道我的约束有什么问题吗? 谢谢!

+0

我使用不同的语法,但从我所看到的,有两件事。首先,20x20按钮相当小。也许他们*被渲染 - 给他们一个backgroundColor来检查。其次,两个按钮都呈现在相同的位置。但从我可以告诉你给他们足够的自动布局知道如何处理它们。 (除非* .notAnAttribute *不正确,我使用“anchor”语法样式,从来没有碰到这个。)编辑:Doh。我没有看到一个按钮正在领先,另一个按钮正在领先。忘记我的第二个评论! – dfd

+1

我相信你希望你的底部和尾部限制是负面的... – DonMag

回答

2

VisualFormat有它的用途,但它也有自己的怪癖 - 比如元素之间的灵活空间。这里有没有VisualFormat一个解决方案:

//: Playground - noun: a place where people can play 

import UIKit 

import PlaygroundSupport 

class MyController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.addButtons() 
    } 

    func addButtons() { 
     let cancelButton = UIButton(type: .custom) 
     let validateButton = UIButton(type: .custom) 

     cancelButton.setImage(UIImage(named: "cancel_icon"), for: .normal) 
     validateButton.setImage(UIImage(named: "validate_icon"), for: .normal) 

     cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) 
     validateButton.addTarget(self, action: #selector(validateAction), for: .touchUpInside) 

     cancelButton.translatesAutoresizingMaskIntoConstraints = false 
     validateButton.translatesAutoresizingMaskIntoConstraints = false 

     self.view.addSubview(cancelButton) 
     self.view.addSubview(validateButton) 

     validateButton.backgroundColor = UIColor.red 
     cancelButton.backgroundColor = UIColor.blue 

     validateButton.setTitle("V", for: UIControlState()) 
     cancelButton.setTitle("C", for: UIControlState()) 

     let leftCancel = NSLayoutConstraint(item: cancelButton, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 16) 
     let bottomCancel = NSLayoutConstraint(item: cancelButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -20) 
     let widthCancel = NSLayoutConstraint(item: cancelButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightCancel = NSLayoutConstraint(item: cancelButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let rightValidate = NSLayoutConstraint(item: validateButton, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: -16) 
     let bottomValidate = NSLayoutConstraint(item: validateButton, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -20) 
     let widthValidate = NSLayoutConstraint(item: validateButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 
     let heightValidate = NSLayoutConstraint(item: validateButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20) 

     NSLayoutConstraint.activate([leftCancel, bottomCancel, rightValidate, bottomValidate, widthCancel, heightCancel, widthValidate, heightValidate]) 

     self.view.layoutIfNeeded() 
    } 

    func cancelAction() { 
     //  self.dismiss(animated: true, completion: nil) 
     print("cancel") 
    } 

    func validateAction() { 
     //  self.dismiss(animated: true, completion: nil) 
     print("validate") 
    } 
} 

var vc = MyController() 
vc.view.backgroundColor = UIColor.green 
vc.view.frame = CGRect(x: 0, y: 0, width: 400, height: 400) 

PlaygroundPage.current.liveView = vc.view 

PlaygroundPage.current.needsIndefiniteExecution = true 

你应该能够复制/粘贴到一个游乐场页面看到的结果。请注意,我没有你的按钮图像,所以我“V”和“C”标题。

关键区别在于将底部和尾部值设置为负值 - 也就是说,您希望按钮的底部为(底部包含视图MINUS 20)。同样,按钮的尾部边缘在包含视图的尾部边缘处为-16。

+0

谢谢,完美,我可以看到我做错了什么!没有考虑负面价值观,我想要有积极的价值,我只需要切换'item:'和'toItem:' –

+0

我把它扔到了操场上,它把80x80图标变成微小的微观10x10图标? –

1

看来你已经过度复杂化了。 您可以使用VisualFormat字符串轻松实现此目的。

看看这里https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html#//apple_ref/doc/uid/TP40010853-CH27-SW1

下面是一个使用你的代码的例子:

func addButtons() { 
    let cancelButton = UIButton(type: .custom) 
    let validateButton = UIButton(type: .custom) 

    cancelButton.setImage(UIImage(named: "cancel_icon"), for: .normal) 
    validateButton.setImage(UIImage(named: "validate_icon"), for: .normal) 

    cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) 
    validateButton.addTarget(self, action: #selector(validateAction), for: .touchUpInside) 

    cancelButton.translatesAutoresizingMaskIntoConstraints = false 
    validateButton.translatesAutoresizingMaskIntoConstraints = false 

    self.view.addSubview(cancelButton) 
    self.view.addSubview(validateButton) 

    // With visual format strings 
    let views = ["cancelButton" : cancelButton, "validateButton" : validateButton] 

    let horizontalFormat = "|[cancelButton]-[validateButton(==cancelButton)]|" 
    let verticalFormat = "V:[cancelButton]-10-|" 

    let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: horizontalFormat, options:.alignAllBottom , metrics: nil, views: views) 
    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: verticalFormat, options:.alignAllBottom, metrics: nil, views: views) 

    NSLayoutConstraint.activate(horizontalConstraints) 
    NSLayoutConstraint.activate(verticalConstraints) 

    self.view.layoutIfNeeded() 
} 
+0

感谢它的工作原理,我接受@DonMag答案,虽然因为它让我明白我的错误是什么!你的允许真的进入视觉格式,我一直在回避,直到那时 –