Skip to content

eonist/Spatial

Repository files navigation

Spatial

mit platform Lang SPM compatible Tests codebeat badge

img

Definition: Spatial | ˈspeɪʃ(ə)l | adjective | describes how objects fit together in space

⚠️ Note: Spatial has been renamed to SpatialLib due to a conflict with a recently introduced framework by Apple also named Spatial. SPM url is the same. Just use import SpatialLib instead of import Spatial

Table of Contents

What is it

Hassle-free AutoLayout, tailored for interactivity and animation. Created for how our mental model thinks autolayout works. Not optimized for brevity.

How does it work

  • Spatial is just extensions and enums which enable you to write less boilerplate code
  • Spatial is interchangeable with Vanilla AutoLayout
  • Spatial comes with examples how you can animate with AutoLayout
  • Spatial uses plain and simple math under the hood.

How do I get it

  • SPM "https://github.com/eonist/Spatial.git" branch: "master"
  • Manual Open Spatial.xcodeproj

Gotchas:

  • SnapKit and Carthography are too clever and caters to too many facets of autolayout. This library is just a simple extension that does basic autolayout while reducing the setup time in half.

Example:

// One-liner, single
btn1.anchorAndSize(to: self, width: 96, height: 24)
// Info regarding parameters and their meaning and effects
btn1.anchorAndSize(to: button, // to what other AutoLayout element should self anchor and size to
		sizeTo: self, // inherit size of another AutoLayout element, overrides to param
		width: 100, // override sizeTo with constant
		height: 50, // override sizeTo with constant
		align: .topCenter, // decides where the pivot of self should be
		alignTo: .bottomCenter, // decides to where self should pivot to
		multiplier: .init(width: 1, height: 1), // multiply sizeTo, or constants
		offset: .init(x: 0, y: 20), // append constant to current position
		sizeOffset: .init(width: -20, height: 0), // append constant to current size
	   	useMargin: false) // adher to other autolayouts margin

// Long-hand, single
btn1.activateAnchorAndSize { view in
	let a = Constraint.anchor(view, to: self)
	let s = Constraint.size(view, width: 96, height: 24)
	return (a, s)
}
// or simpler:
btn1.activateAnchorAndSize {
	Constraint.anchor($0, to: self),
	Constraint.size($0, width: 96, height: 24)
}
// Short-hand, bulk
[btn1, btn2, btn3].distributeAndSize(dir: .vertical, width: 96, height: 24)

// Long-hand, bulk
[btn1,btn2,btn3].activateAnchorsAndSizes { views in
   let anchors = Constraint.distribute(vertically: views, align: .topLeft)
   let sizes = views.map { Constraint.size($0, size: .init(width: 96, height: 42)) }
   return (anchors, sizes)
}
// Pin something between something
$0.activateConstraints { view in
   let tl = Constraint.anchor(view, to: self, align: .topLeft, alignTo: .topLeft)
   let br = Constraint.anchor(view, to: viewFinderView, align: .bottomRight, alignTo: .topRight)
   return [tl.x, tl.y, br.x, br.y] // pins a view to the TR of the parent and BL of another sibling-view
}
// Animation
btn.animate(to: 100,align: left, alignTo: .left)
// Distribute
// |[--][--][--][--][--]|
[label1, label2, label3].activateAnchorsAndSizes { views in // for anim: applyAnchorsAndSizes
   let anchors = Constraint.distribute(vertically: views, align: .left) // there is also: horizontally
   let sizes = views.map{ Constraint.size($0, toView: self.frame.width, height: 48)) }
   return (anchors, sizes)
}
// SpaceAround
// |--[]--[]--[]--[]--[]--|
let views: [ConstraintView] = [UIColor.purple, .orange, .red].map {
   let view: ConstraintView = .init(frame: .zero)
   self.addSubview(view)
   view.backgroundColor = $0
   return view
}
views.applySizes(width: 120, height: 48)
views.applyAnchors(to: self, align: .top, alignTo: .top, offset: 20)
views.spaceAround(dir: .hor, parent: self)
// Space between
// |[]--[]--[]--[]--[]|
views.applySizes(width: 120, height: 48)
views.applyAnchors(to: self, align: .top, alignTo: .top, offset: 20)
views.spaceBetween(dir: .horizontal, parent: self, inset:x)

Todo:

  • Complete the spaceAround and spaceBetween methods ✅
  • Add macOS support ✅
  • Document every param in every declaration (Since the API is more stable now) ✅
  • Make examples with AutoLayout margins not
  • Add methods for applyAnchor for horizontal and vertical types
  • Consider renaming anchor and size to pin and fit
  • Write problem / solution statment in readme?