Searching for greatest practices of utilizing format anchors? Let’s learn to use the iOS autolayout system within the correct approach utilizing Swift.
iOS
Creating views and constraints programmatically
Initially I would wish to recap the UIViewController life cycle strategies, you’re would possibly aware of a few of them. They’re being referred to as within the following order:
- loadView
- viewDidLoad
- viewWillAppear
- viewWillLayoutSubviews
- viewDidLayoutSubviews
- viewDidAppear
Within the pre-auto format period, you needed to do your format calcuations contained in the viewDidLayoutSubviews
methodology, however since this can be a professional auto format tutorial we’re solely going to deal with the loadView
& viewDidLoad
strategies. 🤓
These are the essential guidelines of making view hierarchies utilizing auto format:
- 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 format constraints
NSLayoutConstraint.activate
- Use
loadView
as a substitute ofviewDidLoad
for creating views with constraints - Handle reminiscence administration by utilizing
weak
properties - Set each different property like background coloration, and so forth. in
viewDidLoad
Sufficient idea, 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 = .purple
}
}
Fairly easy, huh? Only a few strains of code and you’ve got a set measurement heart aligned view with a devoted class property reference. Should you create the very same via interface builder, the system will “make” you the loadView
methodology at no cost, however you may must setup an IBOutlet
reference to the view.
The everlasting dilemma: code vs Interface Builder.
It actually would not issues, be at liberty to selected your path. Generally I really like enjoying round with IB, however in a lot of the instances I want the programmatic approach of doing issues. 😛
Frequent UIKit auto format constraint use instances
So I promised that I will present you make constraints programmatically, proper? Let’s try this now. Initially, I take advantage of nothing however format anchors. You may waste your time with the visible format language, however that is undoubtedly a useless finish. So mark my phrases: use solely anchors or stack views, however nothing else! 😇
Listed here are the commonest patterns that I take advantage of to create good layouts. 😉
Set mounted with or top
First one is the most straightforward one: set a view’s top or a width to a set level.
testView.widthAnchor.constraint(equalToConstant: 320),
testView.heightAnchor.constraint(equalToConstant: 240),
Set side ratio
Settings a view’s side ratio is simply constrainting the width to the peak or vica versa, you’ll be able to 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 process, there are particular anchors for that.
testView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
testView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
Stretch | fill inside view with padding
The one tough half right here is that trailing and backside constraints behave a bit bit completely different, than high & main if it involves the constants. Often you must work with unfavorable values, however after a couple 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 top
Should you do not need to work with fixed values, you should utilize the multiplier.
testView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 1/3),
testView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 2/3),
Utilizing protected space format guides
With the newest iPhone you may want some guides with the intention to maintain you protected 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 protected 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 format constraints
Animation with constraints is simple, you should not imagine what others would possibly say. I made some guidelines and an instance that’ll enable you to understanding the essential rules of animating fixed values of a constraint, plus toggling varied constraints. 👍
Guidelines:
- Use commonplace UIView animation with
layoutIfNeeded
- At all times 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 = .purple
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 unhealthy, subsequent: adaptivity and supporting a number of system display screen sizes. 🤔
create adaptive layouts for iOS?
Even Apple is battling adaptive layouts within the built-in iOS purposes. Should you take a look at apps which can be made with assortment views – like pictures – layouts are fairly okay on each system. Nevertheless there are a couple of different ones, that – for my part – are horrible experiences on an even bigger display screen. #justusecollectionviewforeverything. 🤐
Rotation assist
Your first step to adaptive format is supporting a number of system orientations. You’ll be able to test my earlier article about iOS auto format there are many nice stuff inside that article about rotation assist, working with layers inside auto format 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 resembling measurement lessons, show scale, consumer interface idom and lots of extra. Many of the occasions you’ll have to test the vertical & horizontal measurement lessons. There’s a reference of system measurement lessons and all of the attainable variations made by Apple, see the exterior sources part under. 😉
This little Swift code instance under is demonstrating test measurement lessons 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
}
non-public 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 = .purple
}
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()
}
}
System detection
You too can test the consumer interface idom via the UIDevice
class (aka. is that this freakin’ system an iPhone or an iPad?) to set for instance font sizes primarily based on it. 📱
UIDevice.present.userInterfaceIdiom == .pad
Display measurement
An alternative choice to determine your atmosphere is checking the measurement of the display screen. You’ll be able to test the native pixel rely or a relative measurement primarily based 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 state of affairs the place I wanted greater than all of the issues I’ve listed above, however when you’ve got a selected case or questions, please do not hesitate to contact me. 😉