Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Not Apple Autolayout wrapper. Provides placeholders. Linux support.

Overview

CGLayout

Version License Platform

Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Has cross-hierarchy coordinate space. Implementation performed on rect-based constraints.
Fast, asynchronous, declarative, cacheable, extensible. Supported iOS, macOS, tvOS, Linux.

Performed by [LayoutBenchmarkFramework](https://github.com/lucdion/LayoutFrameworkBenchmark)

Quick tutorial

Layout with CGLayout built using layout-blocks. To combine blocks into single unit use LayoutScheme entity (or other entities that has suffix Scheme).

let subviewsScheme = LayoutScheme(blocks: [
// ... layout blocks
])

To define block for "view" element use LayoutBlock entity, or just use convenience getter methods func layoutBlock(with:constraints:).

titleLabel.layoutBlock(
    with: Layout(x: .center(), y: .top(5), width: .scaled(1), height: .fixed(120)),
    constraints: [
        logoImageView.layoutConstraint(for: [.bottom(.limit(on: .inner))])
    ]
)
/// or using anchors
titleLabel.layoutBlock(
    with: Layout(x: .center(), y: .top(5), width: .scaled(1), height: .fixed(120)),
    constraints: { anchors in
        anchors.top.equal(to: logoImageView.layoutAnchors.bottom)
    }
)

For understanding how need to built layout block, let's see layout process in LayoutBlock. For example we have this configuration:

LayoutBlock(
    with: layoutElement, 
    layout: Layout(x: .left(10), y: .top(10), width: .boxed(10), height: .boxed(10)),
    constraints: [
        element1.layoutConstraint(for: [
            .bottom(.limit(on: .outer)), .right(.limit(on: .inner))
        ]),
        element2.layoutConstraint(for: [
            .right(.limit(on: .outer)), .bottom(.limit(on: .inner))
        ])
    ]
)

You have to carefully approach the creation of blocks, because anchors and based on them constraints not have priority and is applying sequentially. Constraints should operate actual frames, therefore next layout block must have constraints with "views", that will not change frame.

Layout anchors are limiters, that is oriented on frame properties (such as sides, size, position).
Any side-based anchors have three base implementations: alignment, limitation(cropping), pulling. Each this implementation have dependency on working space: inner and outer.
Size-based anchors are represented by two implementations: size, insets.
All layout anchors you can find in enum LayoutAnchor.

To create associated layout constraints use protocol LayoutConstraintProtocol.
Framework provides such default implementations:

  • LayoutConstraint: simple associated constraint that uses var frame of passed element to constrain source rect. Use him to build dependency on external workspace.
  • AdjustLayoutConstraint: associated constraint to adjust size of source space. Only elements conform to protocol AdjustableLayoutElement can use it.
  • ContentLayoutConstraint: associated constraint that uses internal bounds to constrain, defined in 'layoutBounds' property of protocol LayoutElement. Use it if you need to create dependency on internal workspace. For example, element inside UIScrollView.
  • AnonymConstraint: constraint to restrict source space independently from external environment.
  • MutableLayoutConstraint: Layout constraint that creates possibility to change active state.
    You can find all this constraints through convenience functions in related elements. Use him to build layout blocks.

In common case, adjust constraints should be apply after any other constraints (but not always).

weatherLabel.layoutBlock(
    with: Layout(x: .left(10), y: .top(), width: .scaled(1), height: .scaled(1)),
    constraints: [
        weatherImageView.layoutConstraint(for: [.top(.limit(.inner)), .right(.limit(.outer)), .height()]),
        weatherLabel.adjustLayoutConstraint(for: [.width()])
    ]
)
AnonymConstraint(anchors: [
    Inset(UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 15))
])

For implementing custom layout entities and save strong typed code, use static func build(_ base: Conformed) -> Self method.

Each layout-block has methods for layout, take snapshot and applying snapshot. Consequently you may use layout-blocks for direct layout, background layout and cached layout:

// layout directly
layoutScheme.layout()

// layout in background
let bounds = view.bounds
    DispatchQueue.global(qos: .background).async {
    let snapshot = self.layoutScheme.snapshot(for: bounds)
    DispatchQueue.main.sync {
        self.layoutScheme.apply(snapshot: snapshot)
    }
}

// cached layout
if UIDevice.current.orientation.isPortrait, let snapshot = portraitSnapshot {
    layoutScheme.apply(snapshot: snapshot)
} else if UIDevice.current.orientation.isLandscape, let snapshot = landscapeSnapshot {
    layoutScheme.apply(snapshot: snapshot)
} else {
    layoutScheme.layout()
}

Typical implementation sizeThatFits(_:) method

func sizeThatFits(_ size: CGSize) -> CGSize {
    let sourceRect = CGRect(origin: .zero, size: size)
    let snapshot = scheme.snapshot(for: sourceRect)
    return snapshot.frame
}

LayoutGuide

Framework provides LayoutGuide as analogue UILayoutGuide. It has possible to generate views and add them to hierarchy.
LayoutGuide can used as invisible limiter and also as layout container.
Default layout containers:

  • StackLayoutGuide - simple implementation of stack.
  • ScrollLayoutGuide - has similar interface with UIScrollView. By use him we can enable scrolling absolutely everywhere.
  • LayoutPlaceholder - single element container that can load view lazily. Has default implementations for CALayer - LayerPlaceholder and UIView - ViewPlaceholder.
  • UIViewPlaceholder - single element container based on UILayoutGuide.

UILayouGuide also adopts LayoutElement protocol. Therefore you can safely build constraints based on UIView.safeAreaLayoutGuide and others.

RTL

To enable Righ-to-Left mode use global configuration:

CGLConfiguration.default.isRTLMode = true

For more details, see documentation and example project.

Code documentation

See here

Example

macOS, iOS, tvOS

To run the example project, clone the repo, and run pod install from the Example directory first.

Linux

To run the example project, clone the repo, and run swift run from the linux_example directory first.

Requirements

Swift 5

Installation

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

pod "CGLayout"

Contributing

I will be happy your feedback, advices and pull requests. For more information read here

Author

Denis Koryttsev Email: [email protected] Twitter: https://twitter.com/K_o_D_e_N

License

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

You might also like...
Written in pure Swift, QuickLayout offers a simple and easy way to manage Auto Layout in code.
Written in pure Swift, QuickLayout offers a simple and easy way to manage Auto Layout in code.

QuickLayout QuickLayout offers an additional way, to easily manage the Auto Layout using only code. You can harness the power of QuickLayout to align

A powerful Swift programmatic UI layout framework.
A powerful Swift programmatic UI layout framework.

Build dynamic and beautiful user interfaces like a boss, with Swift. Neon is built around how user interfaces are naturally and intuitively designed.

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

An easier and faster way to code Autolayout
An easier and faster way to code Autolayout

EZAnchor 中文介绍 An easier way to code Autolayout Are you annoyed of coding .active = true while using Autolayout Anchors over and over again? Are you an

FrameLayoutKit is a super fast and easy to use autolayout kit
FrameLayoutKit is a super fast and easy to use autolayout kit

FrameLayoutKit FrameLayout is a super fast and easy to use layout library for iOS and tvOS. For Objective-C version: NKFrameLayoutKit (Deprecated, not

SwiftLayout - View hierarchy and autolayout DSL library

SwiftLayout view hierarchy and autolayout DSL library goal 뷰의 계층구조와 constraint 관

An extension that simplifies the work with Swift AutoLayout by writing cleaner, more natural and easy-reading code.

Installation For now you're able to clone repo in your project or download ZIP folder manually. git clone https://github.com/votehserxam/AutoLayout.gi

Write concise Autolayout code
Write concise Autolayout code

Winner of Hacking with Swift Recommended award You + Stevia = 🦄 💡 Write concise, readable layouts 🏖 Reduce your maintenance time 🎨 Compose your st

A Swift Autolayout DSL for iOS & OS X
A Swift Autolayout DSL for iOS & OS X

SnapKit is a DSL to make Auto Layout easy on both iOS and OS X. ⚠️ To use with Swift 4.x please ensure you are using = 4.0.0 ⚠️ ⚠️ To use with Swift

Comments
  • Compiler issue

    Compiler issue

    Hi,

    I don't know if you still use this framework, but I can't compile it in XCode : In private.cglayout.swift, lines 62 && 66, compiler doesn't accept the syncGuard syntax :

    Ambiguous use of 'syncGuard(mainThread:)'

    I don't know how to solve it...

    opened by Anard 3
Releases(0.7)
MisterFusion is Swift DSL for AutoLayout. It is the extremely clear, but concise syntax, in addition, can be used in both Swift and Objective-C. Support Safe Area and Size Class.

MisterFusion MisterFusion makes more easier to use AutoLayout in Swift & Objective-C code. Features Simple And Concise Syntax Use in Swift and Objecti

Taiki Suzuki 316 Nov 17, 2022
Custom UIView class that hosts an array of UIbuttons that have an 'underline' UIView beneath them which moves from button to button when the user presses on them.

Swift-Underlined-Button-Bar Custom UIView class that hosts an array of UIbuttons that have an 'underline' UIView beneath them which moves from button

Justin Cook 3 Aug 4, 2022
Apple provides us two ways to use UIKit views in SwiftUI

RepresentableKit Apple provides us two ways to use UIKit views in SwiftUI: UIVie

YUMEMI Inc. 43 Dec 26, 2022
The fast path to autolayout views in code

NorthLayout The fast path to autolayout views in code Talks https://speakerdeck.com/banjun/auto-layout-with-an-extended-visual-format-language at AltC

banjun 36 Jul 15, 2022
Swift-picker-views - inline single and multi picker views for UIKit. Without tableview! Easy and simple

swift-picker-views Inline single and multiple picker views for UIKit. No tablevi

IBRAHIM YILMAZ 2 Jan 31, 2022
A Swift utility to make updating table views/collection views trivially easy and reliable.

ArrayDiff An efficient Swift utility to compute the difference between two arrays. Get the removedIndexes and insertedIndexes and pass them directly a

Adlai Holler 100 Jun 5, 2022
📱AutoLayout can be set differently for each device

DeviceLayout DeviceLayout is a Swift framework that lets you set Auto Layout constraints's differently for each device Using only IBInspector of Xcode

Cruz 171 Oct 11, 2022
Arrange views in your app’s interface using layout tools that SwiftUI provides.

Composing custom layouts with SwiftUI Arrange views in your app's interface using layout tools that SwiftUI provides. Overview This sample app demonst

Apple Sample Code 0 Jun 9, 2022
In SwiftUI, a property-wrapper provides velocity in pt/s from gesture

swiftui-GestureVelocity In SwiftUI, a property-wrapper provides velocity in pt/s from gesture Instructions @GestureVelocity private var velocity: CGVe

Hiroshi Kimura 9 Oct 3, 2022
FlightLayout is a light weight, and easy to learn layout framework as an extension of the UIView.

FlightLayout Introduction FlightLayout is a light weight, and easy to learn layout framework as an extension of the UIView. Functionally, it lives som

Anton 23 Apr 21, 2022