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)