2017-02-13 54 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答案,雖然因爲它讓我明白我的錯誤是什麼!你的允許真的進入視覺格式,我一直在迴避,直到那時 –