DEV Community

Nguyen Truong Ky
Nguyen Truong Ky

Posted on

Starting Auto Layout Programmatically

I published a post to compare Auto Layout Programmatically and Storyboard. 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

Better way: Snapkit

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.

My way: KNConstraint

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

Top comments (0)