Creating views and constraints programmatically
To begin with I would prefer to recap the UIViewController
life cycle strategies, you might be may conversant in a few of them. They’re being referred to as within the following order:
- loadView
- viewDidLoad
- viewWillAppear
- viewWillLayoutSubviews
- viewDidLayoutSubviews
- viewDidAppear
Within the pre-auto structure period, you needed to do your structure calculations contained in the viewDidLayoutSubviews
methodology, however since this can be a professional auto structure tutorial we’re solely going to concentrate on the loadView
& viewDidLoad
strategies. 🤓
These are the essential guidelines of making view hierarchies utilizing auto structure:
- By no means calculate frames manually by your self!
- Initialize your views with
.zero
rect body - Set
translatesAutoresizingMaskIntoConstraints
to false - Add your view to the view hierarchy utilizing
addSubview
- Create and activate your structure constraints
NSLayoutConstraint.activate
- Use
loadView
as a substitute ofviewDidLoad
for creating views with constraints - Deal with reminiscence administration through the use of weak properties
- Set each different property like background shade, and so forth. in
viewDidLoad
Sufficient principle, here’s a quick instance:
class ViewController: UIViewController {
weak var testView: UIView!
override func loadView() {
tremendous.loadView()
let testView = UIView(body: .zero)
testView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(testView)
NSLayoutConstraint.activate([
testView.widthAnchor.constraint(equalToConstant: 64),
testView.widthAnchor.constraint(equalTo: testView.heightAnchor),
testView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
testView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
])
self.testView = testView
}
override func viewDidLoad() {
tremendous.viewDidLoad()
self.testView.backgroundColor = .pink
}
}
Fairly easy, huh? Only a few traces of code and you’ve got a set measurement middle aligned view with a devoted class property reference. In case you create the very same by way of interface builder, the system will “make” you the loadView
methodology without spending a dime, however you may should setup an IBOutlet
reference to the view.
The everlasting dilemma: code vs Interface Builder.
It actually would not issues, be happy to selected your path. Typically I really like taking part in round with IB, however in many of the instances I choose the programmatic method of doing issues. 😛
Frequent UIKit auto structure constraint use instances
So I promised that I am going to present you learn how to make constraints programmatically, proper? Let’s do this now. To begin with, I exploit nothing however structure anchors. You could possibly waste your time with the visible format language, however that is positively a useless finish. So mark my phrases: use solely anchors or stack views, however nothing else! 😇
Listed below are the commonest patterns that I exploit to create good layouts. 😉
Set fastened with or peak
First one is the most straightforward one: set a view’s peak or a width to a set level.
testView.widthAnchor.constraint(equalToConstant: 320),
testView.heightAnchor.constraint(equalToConstant: 240),
Set facet ratio
Settings a view’s facet ratio is simply constrainting the width to the peak or vica versa, you may merely outline the speed by the multiplier.
testView.widthAnchor.constraint(equalToConstant: 64),
testView.widthAnchor.constraint(equalTo: testView.heightAnchor, multiplier: 16/9),
Middle horizontally & vertically
Centering views inside one other one is a trivial job, there are particular anchors for that.
testView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
testView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
Stretch or fill inside view with padding
The one difficult half right here is that trailing and backside constraints behave just a little bit completely different, than prime & main if it involves the constants. Often you must work with detrimental values, however after a number of tries you may perceive the logic right here. 😅
testView.topAnchor.constraint(equalTo: self.view.topAnchor, fixed: 32),
testView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, fixed: 32),
testView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, fixed: -32),
testView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, fixed: -32),
Proportional width or peak
In case you do not wish to work with fixed values, you should use the multiplier.
testView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 1/3),
testView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 2/3),
Utilizing secure space structure guides
With the most recent iPhone you may want some guides with a purpose to preserve you secure from the notch. That is the explanation why views have the safeAreaLayoutGuide property. You will get all the standard anchors after calling out to the secure space information. 💪
testView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
testView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
testView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
testView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
Animating structure constraints
Animation with constraints is straightforward, you should not imagine what others may say. I made some guidelines and an instance that’ll allow you to understanding the essential rules of animating fixed values of a constraint, plus toggling varied constraints. 👍
Guidelines:
- Use normal UIView animation with layoutIfNeeded
- All the time deactivate constraints first
- Maintain to your deactivated constraints strongly
- Have enjoyable! 😛
Constraint animation instance:
class ViewController: UIViewController {
weak var testView: UIView!
weak var topConstraint: NSLayoutConstraint!
var bottomConstraint: NSLayoutConstraint!
var heightConstraint: NSLayoutConstraint!
override func loadView() {
tremendous.loadView()
let testView = UIView(body: .zero)
testView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(testView)
let topConstraint = testView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor)
let bottomConstraint = testView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor)
NSLayoutConstraint.activate([
topConstraint,
testView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
testView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
bottomConstraint,
])
let heightConstraint = testView.heightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.heightAnchor, multiplier: 0.5)
self.testView = testView
self.topConstraint = topConstraint
self.bottomConstraint = bottomConstraint
self.heightConstraint = heightConstraint
}
override func viewDidLoad() {
tremendous.viewDidLoad()
self.testView.backgroundColor = .pink
let faucet = UITapGestureRecognizer(goal: self, motion: #selector(self.tapped))
self.view.addGestureRecognizer(faucet)
}
@objc func tapped() {
if self.topConstraint.fixed != 0 {
self.topConstraint.fixed = 0
}
else {
self.topConstraint.fixed = 64
}
if self.bottomConstraint.isActive {
NSLayoutConstraint.deactivate([self.bottomConstraint])
NSLayoutConstraint.activate([self.heightConstraint])
}
else {
NSLayoutConstraint.deactivate([self.heightConstraint])
NSLayoutConstraint.activate([self.bottomConstraint])
}
UIView.animate(withDuration: 0.25) {
self.view.layoutIfNeeded()
}
}
}
It isn’t that dangerous, subsequent: adaptivity and supporting a number of system display sizes. 🤔
create adaptive layouts for iOS? Even Apple is fighting adaptive layouts within the built-in iOS functions. In case you have a look at apps which might be made with assortment views – like pictures – layouts are fairly okay on each system. Nonetheless there are a number of different ones, that – in my view – are horrible experiences on an even bigger display. 🤐
Rotation help
Your first step to adaptive structure is supporting a number of system orientations. You’ll be able to examine my earlier article about iOS auto structure there are many nice stuff inside that article about rotation help, working with layers inside auto structure land, and so forth. 🌈
Trait collections
Second step is to adapt trait collections. UITraitCollection is there so that you can group all of the environmental particular traits akin to measurement courses, show scale, consumer interface idiom and plenty of extra. Many of the instances you’ll have to examine the vertical & horizontal measurement courses. There’s a reference of system measurement courses and all of the attainable variations made by Apple, see the exterior sources part beneath. 😉
This little Swift code instance beneath is demonstrating learn how to examine measurement courses for setting completely different layouts for compact and common screens.
class ViewController: UIViewController {
weak var testView: UIView!
var regularConstraints: [NSLayoutConstraint] = []
var compactConstraints: [NSLayoutConstraint] = []
override func loadView() {
tremendous.loadView()
let testView = UIView(body: .zero)
testView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(testView)
self.regularConstraints = [
testView.widthAnchor.constraint(equalToConstant: 64),
testView.widthAnchor.constraint(equalTo: testView.heightAnchor),
testView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
testView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
]
self.compactConstraints = [
testView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
testView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
testView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
testView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
]
self.activateCurrentConstraints()
self.testView = testView
}
personal func activateCurrentConstraints() {
NSLayoutConstraint.deactivate(self.compactConstraints + self.regularConstraints)
if self.traitCollection.verticalSizeClass == .common {
NSLayoutConstraint.activate(self.regularConstraints)
}
else {
NSLayoutConstraint.activate(self.compactConstraints)
}
}
override func viewDidLoad() {
tremendous.viewDidLoad()
self.testView.backgroundColor = .pink
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .allButUpsideDown
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
tremendous.traitCollectionDidChange(previousTraitCollection)
self.activateCurrentConstraints()
}
}
Machine detection
It’s also possible to examine the consumer interface idiom by way of the UIDevice
class (aka. is that this freakin’ system an iPhone or an iPad?) to set for instance font sizes based mostly on it. 📱
UIDevice.present.userInterfaceIdiom == .pad
Display screen measurement
An alternative choice to determine your atmosphere is checking the measurement of the display. You’ll be able to examine the native pixel depend or a relative measurement based mostly in factors.
UIScreen.essential.nativeBounds
UIScreen.essential.bounds
Often I am making an attempt to maintain myself to those guidelines. I do not actually bear in mind a situation the place I wanted greater than all of the issues I’ve listed above, however you probably have a selected case or questions, please do not hesitate to contact me. 😉