Reputation: 273
I can not figure out why my button is behaving different when using auto layout constraints programmatically.
When setting the view that holds my cancelBtn every thing is working fine:
let cancelBtnView = TriangularView(frame: CGRect(x: 0, y: 0, width: 300, height: 150))
let cancelBtn = UIButton()
cancelBtnView.addSubview(cancelBtn)
cancelBtn.titleLabel!.font = UIFont.fontAwesome(ofSize: 35, style: .regular)
cancelBtn.setTitle(String.fontAwesomeIcon(name: .times), for: .normal)
cancelBtn.frame = CGRect(x: cancelBtnView.bounds.width / 16, y: cancelBtnView.bounds.height / 2 ,width: 55, height: 55)
I get the following layout:
When setting up the view for my doneBtn I get a different output:
let doneBtnView = TriangularView()
doneBtnView.translatesAutoresizingMaskIntoConstraints = false
doneBtnView.widthAnchor.constraint(equalToConstant: 300).isActive = true
doneBtnView.heightAnchor.constraint(equalToConstant: 150).isActive = true
doneBtnView.trailingAnchor.constraint(equalTo: actionButtonView.trailingAnchor).isActive = true
doneBtnView.bottomAnchor.constraint(equalTo: actionButtonView.bottomAnchor).isActive = true
let doneBtn = UIButton()
doneBtnView.addSubview(doneBtn)
doneBtn.titleLabel!.font = UIFont.fontAwesome(ofSize: 35, style: .regular)
doneBtn.setTitle(String.fontAwesomeIcon(name: .check), for: .normal)
doneBtn.translatesAutoresizingMaskIntoConstraints = false
doneBtn.widthAnchor.constraint(equalToConstant: 55).isActive = true
doneBtn.heightAnchor.constraint(equalToConstant: 55).isActive = true
doneBtn.leadingAnchor.constraint(equalTo: doneBtnView.leadingAnchor, constant: doneBtnView.bounds.width / 16).isActive = true
doneBtn.bottomAnchor.constraint(equalTo: doneBtnView.bottomAnchor, constant: doneBtnView.bounds.height / 2).isActive = true
Setting the constraints for my doneBtn programmatically I get the following:
The constraints for the doneBtnView are set programmatically because I want to pin it to the bottom right of its superview.
Upvotes: 0
Views: 31
Reputation: 154523
Your problem is that you are looking at the bounds of the other view when setting your constraint for your doneBtn
, but those bounds will not have been set yet because layout has not happened. In general, it is a bad idea to combine frame/bounds and constraints.
This can be done, but not with anchors. Try the following NSLayoutConstraint
s:
NSLayoutConstraint(item: doneBtn, attribute: .leading, relatedBy: .equal,
toItem: doneBtnView, attribute: .trailing, multiplier: 1/16, constant: 0).isActive = true
NSLayoutConstraint(item: doneBtn, attribute: .top, relatedBy: .equal,
toItem: doneBtnView, attribute: .bottom, multiplier: 1/2, constant: 0).isActive = true
and then set the width
and height
using anchors:
doneBtn.widthAnchor.constraint(equalToConstant: 55).isActive = true
doneBtn.heightAnchor.constraint(equalToConstant: 55).isActive = true
Note: Because we're using the .trailing
and .bottom
constraints to represent width
and height
, it might be necessary to put doneBtnView
into a container view of the same size because the values will be in the coordinate system of the parent view. By making the parent view the exact same size, width will be equal to the trailing constraint, and height will be equal to the bottom constraint.
Upvotes: 1