Git Product home page Git Product logo

k-o-d-e-n / cglayout Goto Github PK

View Code? Open in Web Editor NEW
44.0 2.0 6.0 5.23 MB

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

Home Page: https://k-o-d-e-n.github.io/CGLayout/

License: MIT License

Ruby 0.49% Swift 99.51%
ui layout-engine layout uikit uiview calayer ios swift autolayout-framework macos

cglayout's Introduction

CGLayout

[DEPRECATED] Replaced with new implementation - LayoutUI

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.

cglayout's People

Contributors

k-o-d-e-n avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

cglayout's Issues

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...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.