Chainable & Lightweight Auto Layout constraints framework for iOS
constraints-kit
Declarative, Chainable & Lightweight Auto Layout constraints framework for iOS. The framework offers a rich set of methods for defining Auto Layout constraints (see Contents) without any other external dependencies.
? Movitation
The purpose of this framework is to provide a very lightweight solution for Auto Layout and to make the development of programmatic UI much simpler, hiding the boilerplate code under the framework. Primary usage is for internal developments, however I decided to share the framework with the community, since it offers some uniqueness and I'm going to continue work on this development.
? Demo
In order to create something like in the following screenshot:
You need to write just a few lines of code:
// 1. First you need to add all your views somewhere. That means your views must have a superview. Let's assume that you have done that.
// 2. Then we assume that visually your views are fully configured.
// 3. And finally, all we need to do is to specify the constraints:
cardView.pinInside(view: self.view, offset: 16)
imageView.pinInside(view: cardView, offset: 8)
blurView.pinInside(view: cardView)
titleLabel.pinTopToTopCenter(of: imageView, offset: 24)
button
.bottom(with: imageView, anchor: .bottom, offset: -34)
.center(in: imageView, axis: .horizontal)
.set(height: 60)
.set(aspect: 2/1)
label
.center(in: imageView)
.left(with: imageView, anchor: .left, offset: 16)
.right(with: imageView, anchor: .right, offset: -16)
Installation
CocoaPods
constraints-kit is availabe via CocoaPods
pod 'constraints-kit', '~> 1.0.0'
Manual
You can always manually add the framework sources into your project. In order to do that just simply copy-paste the following files.
✈️ Usage
The framework is pretty easy to use, however I do recommend to learn the basics of Auto Layout before installing the framework - it will help you to understand what the minimum number of constraints a UIView needs to have and to avoid common pitfalls.
Import
After adding the framework to a project, simply add an import statemt:
import constraints_kit
Setting size
view.set(size: CGSize(width: 300, height: 300))
view.set(width: 400)
view.set(height: 200)
view
.set(width: 200)
.set(aspect: 2/1)
Constraining
A UIImageView fills the parent UIView with offset, until the bottom anchor reaches the top anchor of the UIButton:
imageView
.constrain(using: .top, to: .top, of: view, offset: 24)
.constrain(using: .right, to: .right, of: view, offset: -24)
.constrain(using: .left, to: .left, of: view, offset: 24)
.constrain(using: .bottom, to: .top, of: button, offset: -24)
A UIImageView is anchored at the center of the parent view, it's stretched to the horizontal axis by anchoring left & right sides with the aspect ratio of 3 to 2:
imageView
.center(in: view, axis: .vertical)
.left(with: view, anchor: .left)
.right(with: view, anchor: .right)
.set(aspect: 3/2)
Anchoring
A custom UIView fills a UICollectionViewCell to the top system spacing, with custom left & right offsets and to the top anchor of the UIButton:
presenterView
.topToSystemSpacing(with: view, anchor: .top)
.right( with: view, anchor: .right, offset: -16)
.left( with: view, anchor: .left, offset: 16)
.bottom( with: button, anchor: .top, offset: -16)
A UIButton is placed at the center of the parent view, its bottom anchor is attached to the bottom of the parent view, height is set to 60 with aspect ratio of 2 to 1:
button
.bottom(with: imageView, anchor: .bottom, offset: -34)
.center(in: imageView, axis: .horizontal)
.set(height: 60)
.set(aspect: 2/1)
Pinning
A custom ActivityIndicator view is anchored to the top left corner of the specified view with some offset and size equals to 20 to 20:
activityIndicator
.pinInsideToTopLeftCorner(of: view, offset: 24)
.size(CGSize(width: 20, height: 20))
Advanced case where top left anchor of a custom ProgressView is attached to the top leading corner of the parent view and the bottom right anchor is attached to the top right anchor of the LogIn button:
progressView
.pin(anchors: [.left, .top], toTargetView: view, using: [.leading, .top])
.pin(anchors: [.bottom, .right], toTargetView: button, using: [.right, .top])
Filling
A UITableView is placed inside the parent UIView and fills the top half of it (using left, top, right and centerX anchors):
tableView.fillTopHalf(of: parentView)
A UICollectionView is placed inside the parent UIView and fills the left half of it with the specified offset (using left, top, bottom and centerY anchors):
collectionView.fillLeftHalf(of: splitView, offset: 16)
? Contents
The kit contains several groups of methods, each with a specific purpose. All the groups can be chained together, however you should keep in mind that if you have conflicting constraints or you don't provide enough information for the Auto Layout engine, you will see no effect or some unexpected results. It's assumed that you already know the basics of Auto Layout.
Common
constrain- constrainsselfusing the specifiedAttributeto the specifiedAttributewith respect to the relatedUIView. You may setRelation(which is by default.equal),offset(default is0.0) andmultiplier(default is1.0)fit- placesselfinside the specifiedUIViewwith an optionaloffset(default is0.0)center- centersselfinside the specifiedUIViewusing a concreteAxiscase, with an optionalmultiplier(default is1.0)width- applies width equalization betweenselfand the specifiedUIView. You may change theRelation(default isequal),UILayoutPriority(default isrequired),multiplier(default is1.0) andconstant(default is0.0)height- applies height equalization betweenselfand the specifiedUIView. You may change theRelation(default isequal),UILayoutPriority(default isrequired),multiplier(default is1.0) andconstant(default is0.0)
Setters
set(size:)- sets a newCGSizeforselfby applying layout constaints forwidth&heightanchorsset(width:)- sets a newwidthby applying layout constaint forwidthanchorset(height:)- sets a newheightby applying layout constraint forheightanchorset(aspect:)- sets a newaspect ratioby applying layout constaint foraspectanchorset(aspectOf:)- sets a newaspect ratioby duplicatingaspectof the specifiedUIViewset(value: to:)- sets a new offsetvaluefor theAttribute
Anchoring
top- anchors top anchor to the specifiedUIViewusingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)bottom- anchors bottom anchor to the specifiedUIViewusingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)left- anchors left anchor to the specifiedUIViewusingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)right- anchors right anchor to the specifiedUIViewusingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)
Anchoring to System Spacing
rightToSystemSpacing- anchors right anchor to the specifiedUIViewwith respect to System Spacing usingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)leftToSystemSpacing- anchors left anchor to the specifiedUIViewwith respect to System Spacing usingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)topToSystemSpacing- anchors top anchor to the specifiedUIViewwith respect to System Spacing usingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)bottomToSystemSpacing- anchors bottom anchor to the specifiedUIViewwith respect to System Spacing usingAxisYanchor,Relation(defatul is.equal), NSLayoutPriority (default is.required) andoffset(default is0.0)
Pinning
pinTopLeftToTopLeftCorner- pins Top Left anchor to the Top Left corner of the specifiedUIViewwith a givenoffset(default is0.0)pinTopRightToTopRightCorner- pins Top Right anchor to the Top Right corner of the specifiedUIViewwith a givenoffset(default is0.0)pinBottomRightToBottomRight- pins Bottom Right anchor to the Bottom Right corner of the specifiedUIViewwith a givenoffset(default is0.0)pinBottomLeftToBottomLeft- pins Bottom Left anchor to the Bottom Left corner of the specifiedUIViewwith a givenoffset(default is0.0)pinBottomRightToTopLeft- pins Bottom Right anchor to the Top Left corner of the specifiedUIViewwith a givenoffset(default is0.0)pinBottomLeftToTopRight- pins Bottom Left anchor to the Top Right corner of the specifiedUIViewwith a givenoffset(default is0.0)pinTopLeftToBottomRight- pins Top Left anchor to the Bottom Right corner of the specifiedUIViewwith a givenoffset(default is0.0)pinBottomRightToTopLeft- pins Bottom Right anchor to the Top Left corner of the specifiedUIViewwith a givenoffset(default is0.0)pinTopToTopCenter- pins Top anchor to the Top Center anchor of the specifiedUIViewwith a givenoffset(default is0.0)pinBottomToBottomCenter- pins Bottom anchor to the Bottom Center anchor of the specifiedUIViewwith a givenoffset(default is0.0)pinLeftToLeftCenter- pins Left anchor to the Left Center anchor of the specifiedUIViewwith a givenoffset(default is0.0)pinRightToRightCenter- pins Right anchor to the Right Center anchor of the specifiedUIViewwith a givenoffset(default is0.0)pinInside- pinsselfinside the specifiedUIViewwithRelation(default is.equal), UILayoutPriority (default is.required) andoffset(default is0.0)pinTo- pinsselfto the specifiedUIViewby usingAnchor(which is anOptionSet)pin(anchors:, toTargetView: , using:)- pins the specifiedAnchorsofselfto theUIViewby using the relatedAnchors
Filling
fillBottomHalf- fills the bottom half of the specified view byselfwith the givenoffset(default is0.0)fillTopHalf- fills the top half of the specified view byselfwith the givenoffset(default is0.0)fillLeftHalf- fills the left half of the specified view byselfwith the givenoffset(default is0.0)fillRightHalf- fills the right half of the specified view byselfwith the givenoffset(default is0.0)