Searching for greatest practices of utilizing format anchors? Let’s discover ways to use the iOS autolayout system within the correct method utilizing Swift.
iOS
Creating views and constraints programmatically
To begin with I would wish to recap the UIViewController life cycle strategies, you’re may accustomed to 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
technique, however since this can be a pro auto layout tutorial we’re solely going to give attention to 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 - Deal with reminiscence administration by utilizing
weak
properties - Set each different property like background coloration, and so forth. in
viewDidLoad
Sufficient idea, here’s a brief 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 = .crimson
Fairly easy, huh? Just some strains of code and you’ve got a set measurement middle aligned view with a devoted class property reference. In the event you create the very same by means of interface builder, the system will “make” you the loadView
technique totally free, however you will should setup an IBOutlet
reference to the view.
The everlasting dilemma: code vs Interface Builder.
It actually does not issues, be at liberty to selected your path. Typically I really like enjoying round with IB, however in a lot of the circumstances I favor the programmatic method of doing issues. 😛
Frequent UIKit auto format constraint use circumstances
So I promised that I am going to present you how one can make constraints programmatically, proper? Let’s do this now. To begin with, I take advantage of nothing however format anchors. You may waste your time with the visual format language, however that is positively a useless finish. So mark my phrases: use solely anchors or stack views, however nothing else! 😇
Listed here are the most typical patterns that I take advantage of to create good layouts. 😉
Set fastened with or top
First one is the simplest one: set a view’s top 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’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),
Heart horizontally & vertically
Centering views inside one other one is a trivial activity, 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 prime & main if it involves the constants. Normally it’s important to work with unfavourable values, however after a couple of tries you will 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
In the event you do not need 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 protected space format guides
With the newest iPhone you will want some guides in an effort to maintain you protected from the notch. That is the explanation why views have the safeAreaLayoutGuide
property. You may 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 may say. I made some guidelines and an instance that’ll assist you to understanding the essential rules of animating fixed values of a constraint, plus toggling numerous constraints. 👍
Guidelines:
- Use customary 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 = .crimson
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. 🤔
Learn how to create adaptive layouts for iOS?
Even Apple is battling adaptive layouts within the built-in iOS functions. In the event you have a look at apps which might be made with assortment views – like photographs – layouts are fairly okay on each system. Nonetheless there are a couple of different ones, that – for my part – are horrible experiences on an even bigger display screen. #justusecollectionviewforeverything. 🤐
Rotation help
Your first step to adaptive format is supporting a number of system orientations. You’ll be able to verify my earlier article about iOS auto layout there are many nice stuff inside that article about rotation help, 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 comparable to measurement lessons, show scale, consumer interface idom and lots of extra. A lot of the occasions you’ll have to verify 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 beneath. 😉
This little Swift code instance beneath is demonstrating how one can verify 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
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 = .crimson
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 may also verify the consumer interface idom by means 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
Another choice to determine your atmosphere is checking the size of the screen. You’ll be able to verify the native pixel rely or a relative size based mostly in factors.
UIScreen.fundamental.nativeBounds
UIScreen.fundamental.bounds
Normally I am making an attempt to maintain myself to those guidelines. I do not actually keep 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. 😉