添加约束到一个自定义的UIButton不起作用
您好我有以下代码:添加约束到一个自定义的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)
有人知道我的约束有什么问题吗? 谢谢!
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。
谢谢,完美,我可以看到我做错了什么!没有考虑负面价值观,我想要有积极的价值,我只需要切换'item:'和'toItem:' –
我把它扔到了操场上,它把80x80图标变成微小的微观10x10图标? –
看来你已经过度复杂化了。 您可以使用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()
}
感谢它的工作原理,我接受@DonMag答案,虽然因为它让我明白我的错误是什么!你的允许真的进入视觉格式,我一直在回避,直到那时 –
我使用不同的语法,但从我所看到的,有两件事。首先,20x20按钮相当小。也许他们*被渲染 - 给他们一个backgroundColor来检查。其次,两个按钮都呈现在相同的位置。但从我可以告诉你给他们足够的自动布局知道如何处理它们。 (除非* .notAnAttribute *不正确,我使用“anchor”语法样式,从来没有碰到这个。)编辑:Doh。我没有看到一个按钮正在领先,另一个按钮正在领先。忘记我的第二个评论! – dfd
我相信你希望你的底部和尾部限制是负面的... – DonMag