Below I have included some code for you to checkout. I am trying to take a custom UIView
and add another custom subview to it. This subview should be constrained to the parent view in such a way it essentially just lays on top with the same dimensions and the parent just acts as a wrapper.
I have tried using the NSLayoutConstraint
and failed miserable so far. The view never actually shows up. I have a left, right, bottom, and top constraint which should line up with the parent view.
The first ask I have is that someone please explain and or correct my logic when using the following method. The item param I figured is the actual view you want to set a constraint for (customViewChild
). The attribute is to say that I want the left edge of my customViewChild
to be used for this constraint. The relatedBy
seems pretty straight forward although I could be wrong, and then finally the toItem
points to self which is my CustomViewParent
which also has a .left
attribute to say that I want the left edge of my child and parent to line up. Is this logic flawed or am I doing something else wrong?
NSLayoutConstraint(item: customViewChild!,
attribute: .left,
relatedBy: .equal,
toItem: self,
attribute: .left,
multiplier: 1.0,
constant: 0.0)
I know the following example could very easily be done with IB, but I am trying to understand NSLayoutConstraint
, so please provide answers regarding that. And lastly, if anyone could actually correct this code so I have a working example, that would be awesome.
class CustomViewParent: UIView {
var customViewChild: UIView?
override init(frame: CGRect) {
super.init(frame: frame)
setConstraints()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setConstraints()
}
func setConstraints() {
customViewChild = UIView()
addSubview(customViewChild!)
customViewChild?.translatesAutoresizingMaskIntoConstraints = false
let leftConstraint = NSLayoutConstraint(item: customViewChild!,
attribute: .left,
relatedBy: .equal,
toItem: self,
attribute: .left,
multiplier: 1.0,
constant: 0.0).isActive = true
let rightConstraint = NSLayoutConstraint(item: customViewChild!,
attribute: .right,
relatedBy: .equal,
toItem: self,
attribute: .right,
multiplier: 1.0,
constant: 0.0).isActive = true
let topConstraint = NSLayoutConstraint(item: customViewChild!,
attribute: .top,
relatedBy: .equal,
toItem: self,
attribute: .top,
multiplier: 1.0,
constant: 0.0).isActive = true
let bottomConstraint = NSLayoutConstraint(item: customViewChild!,
attribute: .bottom,
relatedBy: .equal,
toItem: self,
attribute: .bottom,
multiplier: 1.0,
constant: 0.0).isActive = true
customViewChild.addConstraint([leftConstraint, rightConstraint, topConstraint, bottomConstraint]);
}
}
You may find this a bit easier, and more readable...
func setConstraints() {
if customViewChild == nil {
customViewChild = UIView()
addSubview(customViewChild!)
customViewChild?.translatesAutoresizingMaskIntoConstraints = false
customViewChild?.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
customViewChild?.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
customViewChild?.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
customViewChild?.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
}
Three things:
addConstraint
. Just set isActive
to true
for the constraints.isActive
to true
and to assign the result of that to a constant. Setting the isActive
property doesn't return the NSLayoutConstraint
. It returns ()
..leading
and .trailing
instead of .left
and .right
.With these changes, the following should work:
func setConstraints() {
customViewChild = UIView()
addSubview(customViewChild!)
customViewChild?.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: customViewChild!,
attribute: .leading,
relatedBy: .equal,
toItem: self,
attribute: .leading,
multiplier: 1.0,
constant: 0.0).isActive = true
NSLayoutConstraint(item: customViewChild!,
attribute: .trailing,
relatedBy: .equal,
toItem: self,
attribute: .trailing,
multiplier: 1.0,
constant: 0.0).isActive = true
NSLayoutConstraint(item: customViewChild!,
attribute: .top,
relatedBy: .equal,
toItem: self,
attribute: .top,
multiplier: 1.0,
constant: 0.0).isActive = true
NSLayoutConstraint(item: customViewChild!,
attribute: .bottom,
relatedBy: .equal,
toItem: self,
attribute: .bottom,
multiplier: 1.0,
constant: 0.0).isActive = true
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With