[英]Adding constraints to a custom UIButton doesn't work
嗨,我有以下代碼:
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)
有人知道我的約束有什么問題嗎? 謝謝!
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
您應該能夠將其復制/粘貼到Playground頁面中以查看結果。 請注意,我沒有你的按鈕圖像,所以我有“V”和“C”標題。
關鍵區別在於將Bottom和Trailing值設置為負值 - 也就是說,您希望Button的底部為(包含視圖MINUS 20的底部)。 同樣,Button的后緣距離包含視圖的后緣為-16。
看來你已經過度復雜了。 您可以使用VisualFormat
字符串輕松實現此目的。
以下是使用您的代碼的示例:
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()
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.