NSLayoutConstraint style for VFL - ios

"V:|[v(>=height)]-0.0#highPriority-|"
What will be the constraint (NSLayoutConstraint style) for above VFL.
Perhaps its considering view height with greaterThanEqual & bottom constraint with UILayoutPriority.defaultHigh.
Something i used -
let heightConstraint = NSLayoutConstraint(item: self.view!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.greaterThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 0)
let bottomConstraint = NSLayoutConstraint(item: self.view!, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 0)
bottomConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([heightConstraint,bottomConstraint])

Initial Set up for Answer:
let parentView = self.view!
let childView = UIView()
childView.backgroundColor = UIColor.lightGray
childView.translatesAutoresizingMaskIntoConstraints = false
parentView.addSubview(childView)
For given VFL:
"V:|[v(>=height)]-0.0#highPriority-|"
1. VFL Implementation:
let height: CGFloat = 100
let priority: Int = 1000
//VFL (for vertical positioning and height of childView
parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v(>=\(height))]-0.0#\(priority)-|",
options: [],
metrics: nil,
views: ["v" : childView]))
2. NSLayoutConstraint Implementation:
The above VFL's NSLayoutConstraint equivalent is:
let height: CGFloat = 100
//VFL Equivalent: "V:|[v]"
let topConstraint = NSLayoutConstraint(item: childView,
attribute: .top,
relatedBy: .equal,
toItem: parentView,
attribute: .top,
multiplier: 1,
constant: 0)
//VFL Equivalent: "[v(>=height)]"
let heightConstraint = NSLayoutConstraint(item: childView,
attribute: .height,
relatedBy: .greaterThanOrEqual,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 1,
constant: height)
//VFL Equivalent: "[v]|" or "[v]-0.0-|"
let bottomConstraint = NSLayoutConstraint(item: childView,
attribute: .bottom,
relatedBy: .equal,
toItem: parentView,
attribute: .bottom,
multiplier: 1,
constant: 0)
//Adding VFL Equivalent: #priority
bottomConstraint.priority = .defaultHigh
childView.addConstraint(heightConstraint)
parentView.addConstraint(topConstraint)
parentView.addConstraint(bottomConstraint)
NOTE: The given VFL in your question only provides the childViews y position and height.
For width, add the constraints accordingly.
VFL Example for width would be:
parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v(100)]",
options: [],
metrics: nil,
views: ["v" : childView]))
Ref:
Apple's Autolayout Guide on VFL

Related

Hot to add a View to a Scrollview programmatically using layout constraints

I'm triying to instert programatically a view inside an UIScrollView, but it doesn't appear here is my code:
mainScrollView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(mainScrollView)
//Add Trailing
let trailingConstraint = NSLayoutConstraint(item: mainScrollView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: 0)
self.view.addConstraint(trailingConstraint)
//Add Leading
let leadingConstraint = NSLayoutConstraint(item: mainScrollView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 0)
self.view.addConstraint(leadingConstraint)
//Add Top
let topConstraint = NSLayoutConstraint(item: mainScrollView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 0)
self.view.addConstraint(topConstraint)
//Add Bottom
let bottomConstraint = NSLayoutConstraint(item: mainScrollView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 0)
self.view.addConstraint(bottomConstraint)
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.backgroundColor = .blue
mainScrollView.addSubview(contentView)
//Add Trailing
let trailingConstraintContent = NSLayoutConstraint(item: contentView, attribute: .trailing, relatedBy: .equal, toItem: mainScrollView, attribute: .trailing, multiplier: 1, constant: 0)
mainScrollView.addConstraint(trailingConstraintContent)
//Add Leading
let leadingConstraintContent = NSLayoutConstraint(item: contentView, attribute: .leading, relatedBy: .equal, toItem: mainScrollView, attribute: .leading, multiplier: 1, constant: 0)
mainScrollView.addConstraint(leadingConstraintContent)
//Add Top
let topConstraintContent = NSLayoutConstraint(item: contentView, attribute: .top, relatedBy: .equal, toItem: mainScrollView, attribute: .top, multiplier: 1, constant: 0)
mainScrollView.addConstraint(topConstraintContent)
//Add Bottom
let bottomConstraintContent = NSLayoutConstraint(item: contentView, attribute: .bottom, relatedBy: .equal, toItem: mainScrollView, attribute: .bottom, multiplier: 1, constant: 0)
mainScrollView.addConstraint(bottomConstraintContent)
The first ScrollView is inserted because I added a background color and I can see it, but I cant see the contentview added as background color blue.
Any help?
UPDATE
I have tried the following to and no success:
mainScrollView.translatesAutoresizingMaskIntoConstraints = false
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
mainScrollView.backgroundColor = .red
contentView.backgroundColor = .blue
self.view.addSubview(mainScrollView)
mainScrollView.addSubview(contentView)
let viewsDictionary = ["mainScrollView": mainScrollView, "contentView": contentView]
let mainScrollViewVerticalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|[mainScrollView]|", options: [], metrics: nil, views: viewsDictionary)
let mainScrollViewHorizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|[mainScrollView]|", options: [], metrics: nil, views: viewsDictionary)
self.view.addConstraints(mainScrollViewVerticalConstraint)
self.view.addConstraints(mainScrollViewHorizontalConstraint)
let contentViewVerticalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|[contentView]|", options: [], metrics: nil, views: viewsDictionary)
let contentViewHorizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|[contentView]|", options: [], metrics: nil, views: viewsDictionary)
mainScrollView.addConstraints(contentViewVerticalConstraint)
mainScrollView.addConstraints(contentViewHorizontalConstraint)
When adding sub views the important thing to remember is to pin them in a way to make it possible for Auto Layout to evaluate the height, this is because the scroll view determines the content size by determining the sum of heights sub views (in case of vertical).
So you should specify the height in VFL . eg.
let contentViewVerticalConstraint=NSLayoutConstraint.constraints(withVisualFormat: "V:|[contentView(300)]", options: [], metrics: nil, views: viewsDictionary)
Create a custom view using .xib file
Apply the constraints for the custom view child components in .xib (auto layout)
Create a custom view instant
MyView *myview = [[[NSBundle mainBundle] loadNibNamed:#"nibName" owner:nil options:nil] objectAtIndex:0];
Set its frame for screen width as
CGRect screenSize = [UIScreen mainScreen].bounds.size;
myView = CGRectMake(0.0, 0.0, screenSize.width, 100.0);
Add to parent view
[parentView addSubView:myView];

Programmatically create Constraints - 2 Boxes

I would like to to create the following result:
With only manually created NSLayoutConstraints. But at the moment i only have a blue box, or (if i do not add the UIButton) the correct red View.
let newView = UIView()
newView.backgroundColor = UIColor.redColor()
newView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(newView)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
view.addConstraint(verticalConstraint)
let topContraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
view.addConstraint(topContraint)
let bottomContraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomContraint)
let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 200)
view.addConstraint(widthConstraint)
let disableButton = UIButton()
disableButton.backgroundColor = UIColor.blueColor()
disableButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(disableButton)
let leadingConstraint = NSLayoutConstraint(item: disableButton, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
view.addConstraint(leadingConstraint)
let topBContraint = NSLayoutConstraint(item: disableButton, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
view.addConstraint(topBContraint)
let bottomBContraint = NSLayoutConstraint(item: disableButton, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomBContraint)
let trailingConstraint = NSLayoutConstraint(item: disableButton, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: newView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
view.addConstraint(trailingConstraint)
Can anyone help me out whats wrong here? Is there a difference, in which order i create manually the constraints?
Your code can be a lot more compact by using the Visual Format Language:
let newView = UIView()
newView.backgroundColor = UIColor.redColor()
newView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(newView)
let disableButton = UIButton()
disableButton.backgroundColor = UIColor.blueColor()
disableButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(disableButton)
let views = ["newView": newView, "disableButton": disableButton]
let c1 = NSLayoutConstraint.constraintsWithVisualFormat("V:|[newView]|", options: [], metrics: nil, views: views)
let c2 = NSLayoutConstraint.constraintsWithVisualFormat("H:|[newView]|", options: [], metrics: nil, views: views)
let c3 = NSLayoutConstraint.constraintsWithVisualFormat("V:|[disableButton]|", options: [], metrics: nil, views: views)
let c4 = NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[disableButton]", options: [], metrics: nil, views: views)
let c5 = NSLayoutConstraint(item: disableButton, attribute: .Width, relatedBy: .Equal, toItem: newView, attribute: .Width, multiplier: 0.75, constant: 0)
NSLayoutConstraint.activateConstraints(c1 + c2 + c3 + c4)
view.addConstraint(c5)
c1 tells Auto Layout to make the red view fill the superview vertically.
c2 do the same horizontally
c3 tells Auto Layout to make the blue button fill vertically
c4 makes it stick to the left edge of the screen
c5: some constraints cannot be written with the Visual Format Language, hence we need to use a different function to make disableButton.width = newView.width * 0.75
I could have written the last line as
NSLayoutConstraint.activateConstraints(c1 + c2 + c3 + c4 + [c5])
But for some reason this takes ridiculously long to compile. Hence the split you see in the code above.

Make UILabel Constraint to display full width

I'm struggling to implement to make my uilabel to stretch from the left side to right side (Full Width), I can do it easily in storyboard but I have a part on my app that needs to display a uilabel progmatically.
Here's my code:
textLabel.backgroundColor = UIColor.grayColor()
textLabel.text = StringsLabel.NOINTERNET
textLabel.textAlignment = .Center
textLabel.font = UIFont.boldSystemFontOfSize(24.0)
textLabel.translatesAutoresizingMaskIntoConstraints = false
centerView.addSubview(textLabel)
let centreXTopLabel:NSLayoutConstraint = NSLayoutConstraint(item: textLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: centerView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
centerView.addConstraint(centreXTopLabel)
Here's the screenshot of what i've got:
Pin it to the leading and trailing of the view at 0 points:
let leading = NSLayoutConstraint(item: textLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1, constant: 0)
let trailing = NSLayoutConstraint(item: textLabel, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1, constant: 0)
NSLayoutConstraint.activateConstraints([leading, trailing])
Note that this will result in an ambiguous layout — you need to add a constraint that positions the label vertically.
Try this..
let views = ["textLabel" : textLabel]
let formatString = "|-[textLabel]-|"
let constraints = NSLayoutConstraint.constraintsWithVisualFormat(formatString, options:.AlignAllTop , metrics: nil, views: views)
NSLayoutConstraint.activateConstraints(constraints)

If I want to create these constraints programatically, how do I do so?

I have a UITableView with those constraints. I'm trying to create the UITableView programmatically, but still want these constraints in code.
You can do this relatively easy by using visual format language:
Add your view, topLayoutGuide and bottomLayoutGuide to a dictionary. I used views. You also have to set translatesAutoresizingMaskIntoConstraints to false for the constraints to work.
Example:
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[yourView]-(-15)-|", options: [], metrics: nil, views: views))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[topLayout][yourView][botLayout]", options: [], metrics: nil, views: views))
one way to do is :
let newView = UIView()
newView.backgroundColor = UIColor.redColor()
newView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(newView)
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
view.addConstraint(horizontalConstraint)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: -15)
view.addConstraint(verticalConstraint)
let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
view.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
view.addConstraint(heightConstraint)
for more info you can follow this Swift | Adding constraints programmatically

View constraints - fit a subview

I am adding a subview to a view and I want it to fill the height and width of the view. I am having difficulty with constraints. Any help is appreciated. This is what I have currently:
self.view.addSubview(self.mainView)
var leftSideConstraint = NSLayoutConstraint(item: self.mainView, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0)
var bottomConstraint = NSLayoutConstraint(item: self.mainView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
var widthConstraint = NSLayoutConstraint(item: self.mainView, attribute: .Width, relatedBy: .Equal, toItem: self.view, attribute: .Width, multiplier: 1.0, constant: 0.0)
var heightConstraint = NSLayoutConstraint(item: self.mainView, attribute: .Height, relatedBy: .Equal, toItem: self.view, attribute: .Height, multiplier: 1.0, constant: 0.0)
self.view.addConstraints([leftSideConstraint, bottomConstraint, widthConstraint, heightConstraint])
Swift 5
Here is an elegant way with using UIView extension
extension UIView {
func addConstrained(subview: UIView) {
addSubview(subview)
subview.translatesAutoresizingMaskIntoConstraints = false
subview.topAnchor.constraint(equalTo: topAnchor).isActive = true
subview.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
subview.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
subview.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
}
And then you add a subview wherever you need it with
yourContainerView.addConstrained(subview: yourSubview)
The following code should work:
let mainView = UIView() //Make sure your mainView is initialized
mainView.backgroundColor = UIColor.blueColor() //For test purpose
mainView.setTranslatesAutoresizingMaskIntoConstraints(false) //Don't forget this line
view.addSubview(mainView)
var leftSideConstraint = NSLayoutConstraint(item: mainView, attribute: .Left, relatedBy: .Equal, toItem: view, attribute: .Left, multiplier: 1.0, constant: 0.0)
var bottomConstraint = NSLayoutConstraint(item: mainView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
var widthConstraint = NSLayoutConstraint(item: mainView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1.0, constant: 0.0)
var heightConstraint = NSLayoutConstraint(item: mainView, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 1.0, constant: 0.0)
view.addConstraints([leftSideConstraint, bottomConstraint, heightConstraint, widthConstraint])
As an alternative, you can use the Auto layout Visual Format Language:
let mainView = UIView() //Make sure your mainView is initialized
mainView.backgroundColor = UIColor.blueColor() //For test purpose
mainView.setTranslatesAutoresizingMaskIntoConstraints(false) //Don't forget this line
view.addSubview(mainView)
var viewsDict = ["mainView" : mainView]
var horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|[mainView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict)
var verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|[mainView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict)
view.addConstraints(horizontalConstraints)
view.addConstraints(verticalConstraints)

Resources