In the previous post, we have explained how to create UI elements like UILabel, UIButton etc using code. In this post, we will look into how to create Auto Layout constraint using code. This post assume you already know some basic Auto Layout knowledge.
Starting from iOS9, Apple has provided us NSLayoutAnchor which make creating constraint in code simpler.
NSLayoutAnchor are properties available on all UI elements (UIView, UILabel, UIButton etc) that can be used to set constraint on them.
Here are some Anchor types we can modify for the UI elements :
Horizontal Anchors:
- leadingAnchor
- trailingAnchor
- centerXAnchor
Vertical Anchors:
- topAnchor
- bottomAnchor
- centerYAnchor
Size Anchors:
- widthAnchor
- heightAnchor
For example, let's say we want to create a leading, trailing, top and height constraint for a UIView. In Storyboard / Interface Builder, we can create it like this :
To create these constraints in code, we can use anchors like this :
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let greenView = UIView()
greenView.backgroundColor = UIColor.green
// Remember to set this to false, else Auto Layout won't work
greenView.translatesAutoresizingMaskIntoConstraints = false
// Remember to add the greenView to view first before creating constraint,
// Else there will be an error when you run the app
self.view.addSubview(greenView)
greenView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 30.0).isActive = true
// take note of the negative (-30.0),
// because trailing of greenView is on the left of self.view.trailing
greenView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -30.0).isActive = true
greenView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
greenView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
}
We create a leading constraint for the greenView by using greenView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 30.0).isActive = true. This will create a leading constraint with 30.0 constant from the greenView to the root view (ie. self.view). Remember to put isActive = true
at the end of the constraint declaration code to activate it, else the constraint won't work. Same goes to other constraints defined above.
Build and run the code, you will see the result like this :
Here is the explanation of how anchor works :
There you have it! It's really simple to create Auto Layout constraint using the anchor syntax provided by Apple.
We can continue to add another label below the green view and set its center X to equal to greenView's center X :
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let greenView = UIView()
greenView.backgroundColor = UIColor.green
greenView.translatesAutoresizingMaskIntoConstraints = false
// Add another label
let label = UILabel()
label.text = "iPhone XS is a top notch phone"
label.translatesAutoresizingMaskIntoConstraints = false
// Remember to add views first before creating constraint
self.view.addSubview(greenView)
self.view.addSubview(label)
greenView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 30.0).isActive = true
greenView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -30.0).isActive = true
greenView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
greenView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
label.centerXAnchor.constraint(equalTo: greenView.centerXAnchor).isActive = true
// the top of the label is 40pt down from the bottom of greenView
label.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: 40.0).isActive = true
}
Build and run the code, you will see the result like this :
Safe Area Layout Guide
If we run the previous code in iPhone X, you will see that the top part of the green view is cropped đ± :
This is because we have set the topAnchor of the greenView to self.view.topAnchor, which mean the absolute top of the root view.
Apple has introduced Safe Area Layout Guide in iOS 11 which excludes area that might be cropped by the top notch and the rounded corner of the phone. We can change the anchor to set constraint against the safe area instead of absolute top of root view to prevent it being cropped.
// Replace the topAnchor to compare
// greenView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
greenView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
Using the Safe Area Layout Guide's top anchor, the resulting layout looks like this in iPhone X :
When you create constraint in the Storyboard / Interface Builder, it will automatically select Safe Area as comparison.
As a preemptive caution, I advise to always use Safe Area Layout Guide when creating constraint related to root view (self.view) :
greenView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 30.0).isActive = true
greenView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -30.0).isActive = true
greenView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
greenView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
Creating UI + Auto Layout constraint in code is greatly simplified thanks to NSLayoutAnchor and UIKit Initializer (eg: let label = UILabel()
) provided by Apple. These are the basics you need to know to create UI in code.
Further reading
If you are interested to know more about NSLayoutAnchor, I recommend this explanation of NSLayoutAnchor by Keith Harrison.
If you are interested to know more about why translatesAutoresizingMaskIntoConstraints need to be set to false, Keegan Rush explanation on Autoresizing Mask is great!