⚓️ Declarative, extensible, powerful Auto Layout

Overview

EasyAnchor

❤️ Support my apps ❤️

❤️ ❤️ 😇 😍 🤘 ❤️ ❤️

Version Carthage Compatible License Platform Swift

Table of contents

Story

I like to build view in code, so Auto Layout is my definite choice. The syntax has improved over the years, but I always want to do it with minimum effort. More repetitive code makes you tend to do copy paste and produce more bugs.

Read more How to make Auto Layout more convenient in iOS

Auto Layout APIs history

How new APIs were introduced over the years, so you know to set your deployment target

  • NSLayoutConstraint since iOS 6, macOS 10.7
  • isActive since iOS 8, macOS 10.10
  • NSLayoutAnchor, UI|NSLayoutGuide since iOS 9, macOS 10.11

Do you need another Auto Layout framework?

All the Auto Layout frameworks you see are just convenient ways to build NSLayoutConstraint, in fact these are what you normally need

  • Call addSubview so that view is in hierarchy
  • Set translatesAutoresizingMaskIntoConstraints = false
  • Set isActive = true to enable constraints

Most of the time, NSLayoutAnchor is what you need. But if you need more, EasyAnchor can be your choice.

Examples

Tetris

Well, you can use Auto Layout to make Tetris. Auto Layout plays well with affine transform too. See code




activate(
  lineBlock.anchor.left.bottom
)

// later
activate(
  firstSquareBlock.anchor.left.equal.to(lineBlock.anchor.right),
  firstSquareBlock.anchor.bottom
)

// later
activate(
  secondSquareBlock.anchor.right.bottom
)

Piano

This is how to make a piano using apply and fixed spacing. See code

activate(
  c.anchor.left,
  b.anchor.right,
  c.anchor.top.bottom,
  c.anchor.top.bottom.width.apply(to: [d, e, f, g, a, b]),
  c.anchor.fixedSpacingHorizontally(togetherWith: [d, e, f, g, a, b], spacing: 0)
)

activate(
  cd.anchor.top,
  cd.anchor.size.equal.to(c.anchor.size).multiplier(2/3),
  cd.anchor.top.size.apply(to: [de, fg, ga, ab]),
  cd.anchor.centerX.equal.to(c.anchor.right),
  de.anchor.centerX.equal.to(d.anchor.right),
  fg.anchor.centerX.equal.to(f.anchor.right),
  ga.anchor.centerX.equal.to(g.anchor.right),
  ab.anchor.centerX.equal.to(a.anchor.right)
)

More

More example can be found in Example

Features

  • Fluent builder syntax
  • Easy to customize with protocol based
  • Support iOS, macOS
  • Support LayoutGuide
  • Update and reset constraints
  • Find existing constraints
  • Debug constraints
  • Visualize constraints

Basic with Anchor

Access Anchor

Prefer composition over extension, this is how you access anchor. Support View, LayoutGuide, LayoutSupport

let view = UIView()
view.anchor.left.right

let guide = UILayoutGuide()
guide.anchor.width.height

topLayoutGuide.anchor.bottom
bottomLayoutGuide.anchor.top

Activate constraints

Use activate which accepts variadic parameters. This is important, no matter how you create constraints, they don't have any effect until you activate it

activate(
  a.anchor.top.left,
  b.anchor.top.right,
  c.anchor.bottom.left,
  d.anchor.bottom.right
)

Attributes

Supports all attributes you can think of

anchor.top.left.bottom.right
  .leading.trailing
  .topMargin.bottomMargin.leftMargin.rightMargin
  .centerX.centerY
  .centerXWithinMargins.centerXWithinMargins
  .lastBaseline.firstBaseline
  .width.height

Relation

a.anchor.top.equal.to(b.bottom)
a.anchor.width.greaterThanOrEqual.to(b.anchor.height)
a.anchor.width.lessThanOrEqual.to(b.anchor)

Configuration

This is how to apply constant, multiplier, priority, identifier

a.anchor.top.equal.to(b.anchor.bottom)
  .constant(10).multiplier(1.5).priority(999)
  .id("verticalSpacingBetweenA-B")

Reference

Get references to constraints to modify it later on. In the ref closure, we get access to all the created constraints

var constraint: NSLayoutConstraint?
activate(
  view.anchor.center.constant(10).ref({ constraint = $0.first })
)

Convenient attributes

Use convenient attributes which combine multiple inner attributes

a.anchor.center  // centerX, centerY
a.anchor.size  // width, height
a.anchor.edges  // top, right, bottom, left

Convenient methods

Insets

a.anchor.edges.insets(EdgeInsets(top: 1, left: 2, bottom: 3, right: 4))  // top+1, left+2, bottom+3, right+4
a.anchor.edges.insets(5)  // top+5, left+5, bottom-5, right-5

Padding

a.anchor.paddingHorizontally(20) // leading+20, trailing-20
b.anchor.paddingVertically(20)	// top+20, bottom-20

Size

Size to another anchor

a.anchor.height.equal.to(b.anchor.width)
c.anchor.size.equal.to(d.anchor)

Size to a constant

a.anchor.height.equal.to(20)  // height==20
b.anchor.size.equal.to(20)  // width==20, height==20

You can't just use constant because EasyAnchor will infer to the superview

c.anchor.width.constant(20)  // width==superview.width+20

Ratio

a.anchor.height.equal.to(a.anchor.width)  // height==width

Alternatively, you can just use ratio

a.anchor.width.constant(10)
a.anchor.height.ratio(2) // height==width*2
a.anchor.height.constant(10)
a.anchor.width.ratio(2) // width==height*2

Inference

You know what you mostly want to do. So does EasyAnchor 🎉 . It does its best to infer so don't have to write "obvious" code

Most of the time, you want to constraint to the superview

a.anchor.top.left // a.top == a.superview.top, a.left == a.superview.left

Most of the time, you want to constraint to the same attributes

a.anchor.top.bottom.width.equal.to(b.anchor) // a.top == b.top, a.bottom == b.bottom, a.width == b.width

Find existing constraints

You don't need to declare variables to store constraints, you can just retrieve them back

a.anchor.find(.height)?.constant = 100

// later
b.anchor.find(.height)?.constant = 100

// later
c.anchor.find(.height)?.constant = 100

Animation

Animation is simple. You just change your constraint 's isActive or constant properties, then layoutIfNeeded in an animation block. You can use UIView.animate or UIViewPropertyAnimator

// Change constraint
a.anchor.find(.height)?.constant = 100
loginButtonHeightConstraint.isActive = false

let animator = UIViewPropertyAnimator(duration: 1, dampingRatio: 0.7)
animator.addAnimations { [weak self] in
  self?.view.layoutIfNeeded()
}

animator.startAnimation(afterDelay: 1)

Update constraints with Group

activate is just a convenient way to produce group, then set isActive on the Group. If you just want to group a set of constraints, then set isActive later on, use function group

In this example, we have 4 groups, then take turn to toggle which group gets activated

func toggle(_ group: Group) {
  [g1, g2, g3, g4].forEach { g in
    guard let g = g else {
      return
    }

    g.isActive = (g == group)
  }
}

g1 = group(a.anchor.top.left)
g2 = group(a.anchor.top.right)
g3 = group(a.anchor.bottom.right)
g4 = group(a.anchor.bottom.left)

g1.isActive = true

animator = Animator(view: self, animations: [
  {
    self.toggle(self.g2)
  },
  {
    self.toggle(self.g3)
  },
  {
    self.toggle(self.g4)
  },
  {
    self.toggle(self.g1)
  }
  ])

animator.start()

Extensible with ConstraintProducer

Group is a set of NSLayoutConstraint, which are produced by ConstraintProducer

public protocol ConstraintProducer {
  func constraints() -> [NSLayoutConstraint]
}

For now, there is Anchor and Builder which conforms to ConstraintProducer, you can extend EasyAnchor easily by conform to ConstraintProducer. For example

// This accepts a list of views, and build constraints
class MyAwesomeLayout: ConstraintProducer {
  init(views: [UIView]) {
    // Your code goes here
  }

  func constraints() -> [NSLayoutConstraint] {
    // Your code goes here
    return []
  }
}

let awesomeLayout = MyAwesomeLayout(views: [view1, view2])
activate(awesomeLayout)

Build quickly with Builder

Well, Anchor is for making constraints between 2 views. If you want to make constraints for multiple views at once, you can use multiple Anchor. There are some tasks that you do often, let Builder help you. These method below use Builder under the hood

EasyAnchor has a set of builders to help you avoid repetitive tasks and build UIs quickly 😎

Apply

Apply the same anchor to other views

a.anchor.left.height.apply(to: [b, c]),

Paging

Build a paging scrollView horizontally

addSubview(scrollView)
[a, b, c, d].forEach {
  scrollView.addSubview($0)
}

activate(
  scrollView.anchor.edges.insets(8),
  a.anchor.pagingHorizontally(togetherWith: [b, c, d], in: scrollView)
)

Fixed spacing

Add fixed spacing. The views will resize

activate(
  container.anchor.edges.insets(8),
  a.anchor.left.top.bottom,
  c.anchor.right,
  a.anchor.top.bottom.width.apply(to: [b, c]),
  a.anchor.fixedSpacingHorizontally(togetherWith: [b, c], spacing: 50)
)

Dynamic spacing

Add dynamic spacing using LayoutGuide. The spacing will resize

activate(
  container.anchor.edges.insets(8),
  a.anchor.size.equal.to(30),
  b.anchor.size.equal.to(30),
  c.anchor.size.equal.to(30),
  a.anchor.left.centerY,
  a.anchor.centerY.apply(to: [b, c]),
  c.anchor.right,
  a.anchor.dynamicSpacingHorizontally(togetherWith: [b, c])
)

Debug Auto Layout

Support multiple screen sizes

Installation

EasyAnchor is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'EasyAnchor'

EasyAnchor is also available through Carthage. To install just write into your Cartfile:

github "onmyway133/EasyAnchor"

EasyAnchor can also be installed manually. Just download and drop Sources folders in your project.

Author

Khoa Pham, [email protected]

Contributing

We would love you to contribute to EasyAnchor, check the CONTRIBUTING file for more info.

License

EasyAnchor is available under the MIT license. See the LICENSE file for more info.

You might also like...
An Impressive Auto Layout DSL for  iOS, tvOS & OSX. & It is written in pure swift.
An Impressive Auto Layout DSL for iOS, tvOS & OSX. & It is written in pure swift.

KVConstraintKit KVConstraintKit is a DSL to make easy & impressive Auto Layout constraints on iOS, tvOS & OSX with Swift Installation Using CocoaPods

A compact but full-featured Auto Layout DSL for Swift
A compact but full-featured Auto Layout DSL for Swift

Mortar allows you to create Auto Layout constraints using concise, simple code statements. Use this: view1.m_right |=| view2.m_left - 12.0 Instead of:

Auto Layout In Swift Made Easy

Swiftstraints Swiftstraints can turn verbose auto-layout code: let constraint = NSLayoutConstraint(item: blueView, attr

TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use.
TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use.

TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use. Features Pure Swift 5 sweetness. Everything you can do with Auto

Harness the power of AutoLayout NSLayoutConstraints with a simplified, chainable and expressive syntax. Supports iOS and OSX Auto Layout

Masonry Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're

Template auto layout cell for automatically UITableViewCell height calculating
Template auto layout cell for automatically UITableViewCell height calculating

UITableView-FDTemplateLayoutCell Overview Template auto layout cell for automatically UITableViewCell height calculating. Basic usage If you have a se

Yet Another Swift Auto Layout DSL
Yet Another Swift Auto Layout DSL

FormationLayout Documentation FormationLayout is the top level layout class for one root view. FormationLayout takes a UIView as its rootView. transla

Minimal Auto Layout in Swift
Minimal Auto Layout in Swift

Restraint Restraint is a very very small library to help make your use of NSLayoutConstraint in Swift more legible & declarative. Like programmatic vi

Swift microframework for declaring Auto Layout constraints functionally
Swift microframework for declaring Auto Layout constraints functionally

Relayout Relayout is a Swift microframework to make using Auto Layout easier with static and dynamic layouts. Why? If you want to build a UI using App

Comments
  • Framework is not compiling

    Framework is not compiling

    There is an error "Argument labels '(rawValue:)' do not match any available overloads" on 17 line in Anchor+Constraints.swift file. It works if i modify file manually, but it is not the case, hope you will fix it. It is quite sad that there is no contributors here.

    opened by superhard 4
  • Make better algorithm to find constraints

    Make better algorithm to find constraints

    When using the find method, EasyAnchor should lookup for constraints that are equal to the properties inside Anchor.

    For example, I have set the anchor edges; width equal to height. To find the top constraint, I count use something like that anchor.top.find. In a scenario that there are a lot of constraints related to top, I could specify more attributes to find it like anchor.top.priority(750).constant(10)

    opened by brennobemoura 3
  • I have one Question..

    I have one Question..

    I am a big fan of programmatically UI, and so far I am doing everything manually using apple's own API, but it takes a lot of time and I was looking around and found several options. I find your EasyAnchor really clean and short.

    So, My Question is simple, how long you are playing to support this project? I would love to use EasyAnchor on my future project.

    opened by lohenyumnam 2
  • Closes #4

    Closes #4

    So I change the find method to search for all constraints that fit on anchor attributes. The quantity of parameters matters so the find method can find the specific constraint that you want to find. Because constraints are infinity and it is so difficult to find only one, so now find method returns an array of constraints. I tested a lot on my project because I can create and update the same constraint in the same method so I really need this working.

    My idea is if there is an array of constraints that can be equal to anchor attributes view.anchor.top.find(), I will not call the 'activate(...)' method and I will only update the NSLayoutConstraint properties.

    opened by brennobemoura 2
Releases(3.0.1)
Owner
Khoa
Check my apps https://onmyway133.com/apps
Khoa
Lightweight declarative auto-layout framework for Swift

SwiftyLayout SwiftyLayout is a framework that allows to describe layout constraints (ie NSLayoutConstraint) as a simple mathematical formula in a Swif

Hisakuni Fujimoto 15 Nov 7, 2017
Declarative Auto Layout in Swift, clean and simple

Tails Tails is a take on declarative Auto Layout. If you don't like typing (like me), it might be your kind of thing! Tails is written in Swift and cu

Nick Tymchenko 17 Jan 31, 2019
The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. Objective-C and Swift compatible.

The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends UIView/NSView, NSArray, and NSLayoutConstrai

PureLayout 7.6k Jan 6, 2023
Intuitive and powerful Auto Layout library

Align introduces a better alternative to Auto Layout anchors. Semantic. Align APIs focus on your goals, not the math behind Auto Layout constraints. P

Alexander Grebenyuk 338 Oct 18, 2022
Auto Layout (and manual layout) in one line.

Auto Layout (and manual layout) in one line. Quick Look view.bb.centerX().below(view2).size(100) It’s equivalent to iOS 9 API: view.centerXAnchor.cons

Javier Zhang 74 Oct 19, 2022
Auto Layout made easy with the Custom Layout.

Auto Layout made easy with the Custom Layout. Getting started CocoaPods CocoaPods is a dependency manager for Cocoa projects. You can install it with

Malith Nadeeshan 1 Jan 16, 2022
A declarative UIKit for improve layout productivity when developing an iOS application

TifoKit A declarative UIKit for improve layout productivity when developing an iOS application Requirements Min. iOS 11 Swift 5+ Installation Currentl

Tifo Audi A.P 22 Aug 9, 2022
Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. [iOS/macOS/tvOS/CALayer]

Extremely Fast views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainabl

layoutBox 2.1k Dec 22, 2022
Auto Layout made easy

EasyPeasy is a Swift framework that lets you create Auto Layout constraints programmatically without headaches and never ending boilerplate code. Besi

Carlos Vidal 1.9k Dec 23, 2022
Lightweight Swift framework for Apple's Auto-Layout

I am glad to share with you a lightweight Swift framework for Apple's Auto-Layout. It helps you write readable and compact UI code using simple API. A

null 349 Dec 20, 2022