A good place to start is to read through Apple’s documentation for the UIView class.
Install PureLayout. PureLayout provides a developer friendly API for defining layout constraints for Auto Layout. Writing Auto Layout code from scratch isn’t easy, so PureLayout handles most of the complexity for us.
Use cocoapods to add PureLayout to your project.
platform :ios, "10.0" use_frameworks! pod "PureLayout"
Now install the dependency.
pod install
The first time you run this it will create a new project file that ends in
.xcworkspace
. From now on you should open this project in Xcode when working on the project.Build a custom class. Create a new file called
ProfileView.swift
and add the following code:import UIKit class ProfileView: UIView { }
Next, add our initializers.
import UIKit class ProfileView: UIView { override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } }
We also want to override the
updateConstraints
method on the UIView so that PureLayout can set up our auto layout constraints. SinceupdateConstraints
can be called multiple times once it’s initialized, add a boolean variable calledshouldSetupConstraints
to our class and toggle it off once it’s called once. Note that we also importPureLayout
in this step.import UIKit import PureLayout class ProfileView: UIView { var shouldSetupConstraints = true override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func updateConstraints() { if (shouldSetupConstraints) { // AutoLayout constraints shouldSetupConstraints = false } super.updateConstraints() } }
Now comes the fun part. We want our profile view to contain a
mainPhoto
,bannerPhoto
, and acallToAction
components so we will create them now. First declare the three objects in ourProfileView
class.import UIKit import PureLayout class ProfileView: UIView { var shouldSetupConstraints = true var bannerPhotoView: UIImageView! var mainPhotoView: UIImageView! var callToActionButton: UIButton! override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func updateConstraints() { if (shouldSetupConstraints) { // AutoLayout constraints shouldSetupConstraints = false } super.updateConstraints() } }
Now we’re ready to create our components and add them to our
ProfileView
view. First set the background color ofProfileView
to white. Then configure thebannerPhotoView
,mainPhotoView
, andcallToActionButton
and add them to the view.Notice how we’re initializing each component’s frame to zero. That’s because we’re going to allow Auto Layout to take care of that later.
import UIKit import PureLayout class ProfileView: UIView { var shouldSetupConstraints = true var bannerPhotoView: UIImageView! var mainPhotoView: UIImageView! var callToActionButton: UIButton! let screenSize = UIScreen.main.bounds let edgesInset: CGFloat = 10.0 let centerOffset: CGFloat = 62.0 override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.white bannerPhotoView = UIImageView(frame: CGRect.zero) bannerPhotoView.backgroundColor = UIColor.gray bannerPhotoView.autoSetDimension(.height, toSize: screenSize.width / 3) mainPhotoView = UIImageView(frame: CGRect.zero) mainPhotoView.backgroundColor = UIColor.gray mainPhotoView.layer.borderColor = UIColor.white.cgColor mainPhotoView.layer.borderWidth = 1.0 mainPhotoView.layer.cornerRadius = 5.0 mainPhotoView.autoSetDimension(.width, toSize: 124.0) mainPhotoView.autoSetDimension(.height, toSize: 124.0) callToActionButton = UIButton(frame: CGRect(x: edgesInset, y: screenSize.height - 100, width: screenSize.width - (edgesInset * 2), height: 50)) callToActionButton.layer.cornerRadius = 5.0 callToActionButton.backgroundColor = UIColor(red: 10/255, green: 178/255, blue: 89/255, alpha: 1.0) /* #0ab259 */ callToActionButton.setTitle("Book", for: .normal) callToActionButton.addTarget(self, action: #selector(callToActionButtonAction), for: .touchUpInside) self.addSubview(bannerPhotoView) self.addSubview(mainPhotoView) self.addSubview(callToActionButton) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func updateConstraints() { if (shouldSetupConstraints) { // AutoLayout constraints shouldSetupConstraints = false } super.updateConstraints() } }
Now we’re ready to start pinning our components and letting Auto Layout take care of the rest.
import UIKit import PureLayout class ProfileView: UIView { var shouldSetupConstraints = true var bannerPhotoView: UIImageView! var mainPhotoView: UIImageView! var callToActionButton: UIButton! let screenSize = UIScreen.main.bounds let edgesInset: CGFloat = 10.0 let centerOffset: CGFloat = 62.0 override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.white bannerPhotoView = UIImageView(frame: CGRect.zero) bannerPhotoView.backgroundColor = UIColor.gray bannerPhotoView.autoSetDimension(.height, toSize: screenSize.width / 3) mainPhotoView = UIImageView(frame: CGRect.zero) mainPhotoView.backgroundColor = UIColor.gray mainPhotoView.layer.borderColor = UIColor.white.cgColor mainPhotoView.layer.borderWidth = 1.0 mainPhotoView.layer.cornerRadius = 5.0 mainPhotoView.autoSetDimension(.width, toSize: 124.0) mainPhotoView.autoSetDimension(.height, toSize: 124.0) callToActionButton = UIButton(frame: CGRect(x: edgesInset, y: screenSize.height - 100, width: screenSize.width - (edgesInset * 2), height: 50)) callToActionButton.layer.cornerRadius = 5.0 callToActionButton.backgroundColor = UIColor(red: 10/255, green: 178/255, blue: 89/255, alpha: 1.0) /* #0ab259 */ callToActionButton.setTitle("Book", for: .normal) callToActionButton.addTarget(self, action: #selector(callToActionButtonAction), for: .touchUpInside) self.addSubview(bannerPhotoView) self.addSubview(mainPhotoView) self.addSubview(callToActionButton) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func updateConstraints() { if (shouldSetupConstraints) { bannerPhotoView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .bottom) mainPhotoView.autoPinEdge(toSuperviewEdge: .left, withInset: edgesInset) mainPhotoView.autoPinEdge(.bottom, to: .bottom, of: bannerPhotoView, withOffset: centerOffset) callToActionButton.autoPinEdge(toSuperviewEdge: .bottom, withInset: edgesInset) callToActionButton.autoPinEdge(toSuperviewEdge: .left, withInset: edgesInset) callToActionButton.autoPinEdge(toSuperviewEdge: .right, withInset: edgesInset) shouldSetupConstraints = false } super.updateConstraints() } @objc func callToActionButtonAction(sender: UIButton!) { print("Button tapped") } }
Almost done! Last thing we need to do is initialize our
ProfileView
object when our ViewController callsviewDidLoad
. Go toViewController.swift
and add the following toviewDidLoad
. Make sure to declare ourProfileView
object up top too.import UIKit class ViewController: UIViewController { var profile: ProfileView! override func viewDidLoad() { super.viewDidLoad() profile = ProfileView(frame: CGRect.zero) self.view.addSubview(profile) // AutoLayout profile.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets.zero) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
If all went according to plan you should be able to run your app and see the following components: