My goal in this tutorial is to create views using constraints. I will try to use it in such a way that, anyone can use these constraints to build a more complex layout. The view I would like to create is similar to a UITableViewCell.
Create a view and place it at the top of the superview. For every view, you need to set translatesAutoresizingMaskIntoConstraints = false
otherwise the custom auto layout constraints won’t work.
override func viewDidLoad() {
super.viewDidLoad()
let roundView = UIView()
roundView.backgroundColor = .purple
roundView.translatesAutoresizingMaskIntoConstraints = false
roundView.layer.cornerRadius = 50
view.addSubview(roundView)
view.backgroundColor = .yellow
let margins = view.layoutMarginsGuide
roundView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
roundView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0).isActive = true
roundView.heightAnchor.constraint(equalToConstant: 100).isActive = true
roundView.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
If your view is the top most view, make use of the safeAreaLayoutGuide to help with safe area insets. roundView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0).isActive = true
If you don’t use this, then your view will get clipped.

Move the view to the bottom of the screen. Let’s make use of the bottomAnchor constraint. Use the code below.
let margins = view.layoutMarginsGuide
roundView.leadingAnchor.constraint(equalTo:margins.leadingAnchor).isActive = true
roundView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor, constant: 0.0).isActive = true
roundView.heightAnchor.constraint(equalToConstant: 100).isActive = true
roundView.widthAnchor.constraint(equalToConstant: 100).isActive = true

Map the view to center of the screen.
roundView.centerXAnchor.constraint(equalTo:margins.centerXAnchor).isActive = true
roundView.centerYAnchor.constraint(equalTo:margins.centerYAnchor).isActive = true

Move the view to the right side of the screen.
roundView.trailingAnchor.constraint(equalTo:view.safeAreaLayoutGuide.trailingAnchor, constant: 0.0).isActive = true

Add a label to the right of the view. Let’s call it the title label.
let margins = view.layoutMarginsGuide
// set the height and width
roundView.heightAnchor.constraint(equalToConstant: 100).isActive = true
roundView.widthAnchor.constraint(equalToConstant: 100).isActive = true
// set the position to the top most of the screen
roundView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
roundView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10.0).isActive = true
// add another label to right of the round view
let title = UILabel()
title.translatesAutoresizingMaskIntoConstraints = false
title.text = "This is the title"
view.addSubview(title)
title.heightAnchor.constraint(equalToConstant: 40).isActive = true
title.backgroundColor = .red
title.leadingAnchor.constraint(equalTo: roundView.trailingAnchor, constant: 10).isActive = true
title.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 10).isActive = true
title.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10.0).isActive = true

Let’s add a subtitle to the view
let subtitle = UILabel()
subtitle.translatesAutoresizingMaskIntoConstraints = false
subtitle.text = "This is the subtitle"
view.addSubview(subtitle)
subtitle.heightAnchor.constraint(equalToConstant: 40).isActive = true
subtitle.backgroundColor = .brown
subtitle.leadingAnchor.constraint(equalTo: roundView.trailingAnchor, constant: 10).isActive = true
subtitle.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 10).isActive = true
subtitle.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 10).isActive = true

The magic of using AutoLayout. It will work automatically for Right to left languages and also different orientations, as shown below.


Moving on, let’s consider you want to manage both regular and compact views in your code. You can use an array of NSLayoutConstraints and manage the views accordingly. I will be showing you how this can be done for a compact view. Try doing the same for a regular view. It’s pretty straight forward. The entire code base is as shown below.
import UIKit
class ViewController: UIViewController {
var regularConstraints = [NSLayoutConstraint]()
var compactConstraints = [NSLayoutConstraint]()
private func enableConstraintsForWidth(horizontalSizeClass: UIUserInterfaceSizeClass) {
if horizontalSizeClass == .regular {
NSLayoutConstraint.deactivate(compactConstraints)
NSLayoutConstraint.activate(regularConstraints)
} else {
NSLayoutConstraint.deactivate(regularConstraints)
NSLayoutConstraint.activate(compactConstraints)
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass {
enableConstraintsForWidth(horizontalSizeClass: traitCollection.horizontalSizeClass)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let roundView = UIView()
roundView.backgroundColor = .purple
roundView.translatesAutoresizingMaskIntoConstraints = false
roundView.layer.cornerRadius = 50
view.addSubview(roundView)
view.backgroundColor = .yellow
let margins = view.layoutMarginsGuide
// set the height and width
roundView.heightAnchor.constraint(equalToConstant: 100).isActive = true
roundView.widthAnchor.constraint(equalToConstant: 100).isActive = true
// set the position to the top most of the screen
compactConstraints.append(roundView.leadingAnchor.constraint(equalTo: margins.leadingAnchor))
compactConstraints.append(roundView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10.0))
// add another label to right of the round view
let title = UILabel()
title.translatesAutoresizingMaskIntoConstraints = false
title.text = "This is the title"
view.addSubview(title)
compactConstraints.append(title.heightAnchor.constraint(equalToConstant: 40))
title.backgroundColor = .red
compactConstraints.append(title.leadingAnchor.constraint(equalTo: roundView.trailingAnchor, constant: 10))
compactConstraints.append(title.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 10))
compactConstraints.append(title.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10.0))
let subtitle = UILabel()
subtitle.translatesAutoresizingMaskIntoConstraints = false
subtitle.text = "This is the subtitle"
view.addSubview(subtitle)
subtitle.heightAnchor.constraint(equalToConstant: 40).isActive = true
subtitle.backgroundColor = .brown
compactConstraints.append(subtitle.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 10.0))
compactConstraints.append(subtitle.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 10))
compactConstraints.append(subtitle.leadingAnchor.constraint(equalTo: title.leadingAnchor, constant: 10.0))
if self.traitCollection.horizontalSizeClass != .regular {
enableConstraintsForWidth(horizontalSizeClass: traitCollection.horizontalSizeClass)
}
}
}
Leave a Reply