Starting Auto Layout Programmatically
I published a post to compare Auto Layout Programmatically and Storyboard and got lot of views. This subject has no correct answer at all. It depends on you and your experience.
I wasn't able to live without Storyboard until I found the pain in Storyboard. Today I tell you how I started using Auto Layout Programmatically (ALP) and how I use it in my company projects everyday.
How I started
I followed some cources from Let's Build That App and learned how to use ALP by default code from Apple. Really good source to start ALP.
Today, I demonstrate how to use ALP with 3 different ways. I implement this screen by 3 ways and you can pick the best one for you.
Let's do it.
Define controls
Define and format background image view, some buttons. These controls are same for all ways in this post. We just focus on how to setup Auto Layout by code.
let imgView = UIImageView(image: UIImage(named: "air_balloon"))
imgView.translatesAutoresizingMaskIntoConstraints = false
imgView.contentMode = .scaleAspectFill
let termLabel = UILabel()
termLabel.translatesAutoresizingMaskIntoConstraints = false
termLabel.textAlignment = .center
termLabel.numberOfLines = 0
termLabel.text = "By signing up, you agree to our Terms & Privacy Policy"
termLabel.textColor = .white
let fbLoginButton = UIButton()
fbLoginButton.translatesAutoresizingMaskIntoConstraints = false
fbLoginButton.setTitle("Login with Facebook", for: .normal)
fbLoginButton.setTitleColor(.white, for: .normal)
fbLoginButton.backgroundColor = UIColor(red: 123/255, green: 107/255, blue: 173/255, alpha: 1)
let registerEmailButton = UIButton()
registerEmailButton.translatesAutoresizingMaskIntoConstraints = false
registerEmailButton.setTitle("Sign up with email", for: .normal)
registerEmailButton.setTitleColor(.white, for: .normal)
registerEmailButton.backgroundColor = UIColor(red: 163/255, green: 128/255, blue: 190/255, alpha: 1)
let loginButton = UIButton()
loginButton.translatesAutoresizingMaskIntoConstraints = false
loginButton.setTitle("I already have an account", for: .normal)
loginButton.setTitleColor(.white, for: .normal)
loginButton.backgroundColor = UIColor(red: 171/255, green: 163/255, blue: 177/255, alpha: 1)
Default way
Default syntax from Apple. Quite standard and important. You have to understand these syntax completely. Never depend 100% on any libraries.
view.addSubview(imgView)
imgView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
imgView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
imgView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
imgView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
view.addSubview(termLabel)
termLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true
termLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true
view.addSubview(fbLoginButton)
fbLoginButton.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
fbLoginButton.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
fbLoginButton.heightAnchor.constraint(equalToConstant: 64).isActive = true
view.addSubview(registerEmailButton)
registerEmailButton.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
registerEmailButton.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
registerEmailButton.heightAnchor.constraint(equalToConstant: 64).isActive = true
view.addSubview(loginButton)
loginButton.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
loginButton.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
loginButton.heightAnchor.constraint(equalToConstant: 48).isActive = true
loginButton.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
registerEmailButton.bottomAnchor.constraint(equalTo: loginButton.topAnchor).isActive = true
fbLoginButton.bottomAnchor.constraint(equalTo: registerEmailButton.topAnchor).isActive = true
termLabel.bottomAnchor.constraint(equalTo: fbLoginButton.topAnchor, constant: -16).isActive = true
Pros
- Default ways, not depends on any libraries
- You remember the syntax.
Cons
- Boring: Type or copy/paste same things many times.
- Many lines of code.
Notes
- You can add functions to shorten your code. I leave it for you.
- Important: You have to understand how default syntax work before moving to any libraries
Snapkit
Better way:Snapkit is very popular and has 14,245 stars on Github. You can try some alternative libs
view.addSubview(imgView)
imgView.snp.makeConstraints({ (make) in
make.left.equalToSuperview()
make.right.equalToSuperview()
make.top.equalToSuperview()
make.bottom.equalToSuperview()
})
view.addSubview(termLabel)
termLabel.snp.makeConstraints { (make) in
make.left.equalToSuperview().offset(16)
make.right.equalToSuperview().offset(-16)
}
view.addSubview(fbLoginButton)
fbLoginButton.snp.makeConstraints { (make) in
make.left.equalToSuperview()
make.right.equalToSuperview()
make.height.equalTo(64)
}
view.addSubview(registerEmailButton)
registerEmailButton.snp.makeConstraints { (make) in
make.left.equalToSuperview()
make.right.equalToSuperview()
make.height.equalTo(64)
}
view.addSubview(loginButton)
loginButton.snp.makeConstraints { (make) in
make.left.equalToSuperview()
make.right.equalToSuperview()
make.bottom.equalToSuperview()
make.height.equalTo(32)
}
registerEmailButton.snp.makeConstraints { (make) in
make.bottom.equalTo(loginButton.snp.top)
}
fbLoginButton.snp.makeConstraints { (make) in
make.bottom.equalTo(registerEmailButton.snp.top)
}
termLabel.snp.makeConstraints { (make) in
make.bottom.equalTo(fbLoginButton.snp.top).inset(-16)
}
Pros
- Quite better, shorter syntax
- Easier to read
Cons
- Have a middle man
snp
. Not cool with me - Have a closure to setup layout
- Single constraints are not in good syntax.
KNConstraint
My way:Honestly, I was affected by Robert-Hein Hooijmans to write this extension. Love how he write his lib, TinyConstraint.
I do something different in my extension, and shorten the syntax.
view.addSubviews(views: imgView, termLabel, fbLoginButton, registerEmailButton, loginButton)
imgView.fill(toView: view)
termLabel.horizontal(toView: view, space: 16)
termLabel.verticalSpacingDown(toView: fbLoginButton, space: -16)
fbLoginButton.horizontal(toView: view)
fbLoginButton.height(64)
fbLoginButton.verticalSpacingDown(toView: registerEmailButton)
registerEmailButton.horizontal(toView: view)
registerEmailButton.height(64)
registerEmailButton.verticalSpacingDown(toView: loginButton)
loginButton.horizontal(toView: view)
loginButton.bottom(toView: view)
loginButton.height(32)
Pros
- Very short syntax
- Easy to read, like a short paragraph.
Cons
- Some new term like
horizontal
,vertical
,verticalSpacing
,verticalSpacingDown
Conclusion
I show you 3 different ways to setup Auto Layout by code. There are pros and cons in every way.
Select a good way for you to start Auto Layout Programmatically.
You can download the demo at my Github.
Enjoy coding