A powerful Swift programmatic UI layout framework.

Related tags

Layout Neon
Overview

logo

Build dynamic and beautiful user interfaces like a boss, with Swift.

License Build Status Badge w/ Version Coverage Status Carthage compatible CocoaPods

Neon is built around how user interfaces are naturally and intuitively designed. No more springs and struts. No more whacky visual format language. No more auto layout constraints. We're not robots, so why should we build our UIs like we are?

Neon has been updated to Swift 3.0, but is still currently in beta!

Install via CocoaPods

You can use Cocoapods to install Neon by adding it to your Podfile:

platform :ios, '9.0'
use_frameworks!
pod 'Neon'

##Manual Installation

  1. Download and drop /Source in your project.
  2. Congratulations!

To get the full benefits import Neon wherever you have a UIView operation:

import UIKit
import Neon

Example

facebook

Rather than design some arbitrary layout for a demonstration, I figured a good test for the practicality of Neon would be to replicate an existing screen from a major app, one that everyone could recognize. The above screenshot on the left is my profile in the Facebook app, and the screenshot on the right is from the Neon demo project.

Facebook's profile screen was surely built using some form of UITableView or UICollectionView, but for the sake of simple demonstration I built the top-most major components of the profile in a normal UIViewController. After all the customization of the subviews to make them as close to Facebook's design as possible (I tried my best), this is what I came up with for the layout:

let isLandscape : Bool = UIDevice.currentDevice().orientation.isLandscape.boolValue
let bannerHeight : CGFloat = view.height() * 0.43
let avatarHeightMultipler : CGFloat = isLandscape ? 0.75 : 0.43
let avatarSize = bannerHeight * avatarHeightMultipler

searchBar.fillSuperview()
bannerImageView.anchorAndFillEdge(.Top, xPad: 0, yPad: 0, otherSize: bannerHeight)
bannerMaskView.fillSuperview()
avatarImageView.anchorInCorner(.BottomLeft, xPad: 15, yPad: 15, width: avatarSize, height: avatarSize)
nameLabel.alignAndFillWidth(align: .ToTheRightCentered, relativeTo: avatarImageView, padding: 15, height: 120)
cameraButton.anchorInCorner(.BottomRight, xPad: 10, yPad: 7, width: 28, height: 28)
buttonContainerView.alignAndFillWidth(align: .UnderCentered, relativeTo: bannerImageView, padding: 0, height: 62)
buttonContainerView.groupAndFill(group: .Horizontal, views: [postButton, updateInfoButton, activityLogButton, moreButton], padding: 10)
buttonContainerView2.alignAndFillWidth(align: .UnderCentered, relativeTo: buttonContainerView, padding: 0, height: 128)
buttonContainerView2.groupAndFill(group: .Horizontal, views: [aboutView, photosView, friendsView], padding: 10)

portrait

Looks pretty good on every device size! Now, keep in mind you'll probably want constants defined for many of these size/padding values, in order to keep the code cleaner and easier to maintain, but I decided to use real numbers for most of the values to make the code less obscure when new people are reading through the demonstration. Now, unlike Facebook's iPhone app the layout built with Neon is dynamic. It is able to handle rotation on all-sized devices with no problem:

landscape

###Not bad for 10 lines of code!

Here's an intentionally convoluted example to show how easy it is to build very complex and dynamic layouts with Neon. The following layout was created with only 20 lines of code. That's one line of code per view! While impressive, this layout is horrifying and should never be used in an actual app... ever...

Demo

Anchoring Views

Center

There are a few ways you can anchor views using Neon, and the first and most simple is anchoring a view in the center of its superview:

view1.anchorInCenter(width: size, height: size)

Center

Filling Superview

Sometimes you want a view to fill its superview entirely, which couldn't be easier.

view.fillSuperview()

Optionally, if you want a view to fill its superview with padding, you can provide padding instead:

view1.fillSuperview(left: padding, right: padding, top: padding, bottom: padding)

Fill

Corner

The second anchoring method is anchoring a view in its superview's Corner. As you might have guessed, the four corners are .TopLeft, .TopRight, .BottomLeft, .BottomRight, and coupled with the anchorInCorner() function, you can easily anchor a view in any corner like this:

view1.anchorInCorner(.TopLeft, xPad: padding, yPad: padding, width: size, height: size)
view2.anchorInCorner(.TopRight, xPad: padding, yPad: padding, width: size, height: size)
view3.anchorInCorner(.BottomLeft, xPad: padding, yPad: padding, width: size, height: size)
view4.anchorInCorner(.BottomRight, xPad: padding, yPad: padding, width: size, height: size)

Corner

Edge

Edge is another pretty obvious one to follow - it specifies on what edge of its superview a view will be anchored to. The four types are .Top, .Left, .Bottom, or .Right, and similar to previous examples, you can use the anchorToEdge() function to anchor a view to an edge:

view1.anchorToEdge(.Top, padding: padding, width: size, height: size)
view2.anchorToEdge(.Left, padding: padding, width: size, height: size)
view3.anchorToEdge(.Bottom, padding: padding, width: size, height: size)
view4.anchorToEdge(.Right, padding: padding, width: size, height: size)

Edge

Filling an edge

Sometimes, you want to anchor a view against an edge, filling that edge; imagine something like a banner photo for a profile page. Again, this is made as simple as possible using the anchorAndFillEdge() function:

view1.anchorAndFillEdge(.Top, xPad: padding, yPad: padding, otherSize: size)
view2.anchorAndFillEdge(.Bottom, xPad: padding, yPad: padding, otherSize: size)
view3.anchorAndFillEdge(.Left, xPad: padding, yPad: padding, otherSize: size)
view4.anchorAndFillEdge(.Right, xPad: padding, yPad: padding, otherSize: size)

Fill Edge

Note that anchorAndFillEdge() accepts a parameter called otherSize. That parameter is used to set the other size that isn't automatically calculated by filling the edge, meaning that if you specify that you want to anchor to and fill the top edge, the width will be automatically calculated, but the height is still unknown, so the value passed in to otherSize will be used to set the height. Subsequently, if you want to anchor to and fill the left edge, the height is automatically calculated and otherSize will be used to set the width of the view.

Align

Now that we've anchored primary views, we can start making our UI more complex by aligning other views relative to other sibling views, using the (you guessed it) Align value. Sibling views are views that share the same superview directly. There are twelve Align types, and they are all pretty self-explanatory - here's an example using all twelve with the align() function:

view1.align(.AboveMatchingLeft, relativeTo: anchorView, padding: padding, width: size, height: size)
view2.align(.AboveCentered, relativeTo: anchorView, padding: padding, width: size, height: size)
view3.align(.AboveMatchingRight, relativeTo: anchorView, padding: padding, width: size, height: size)
view4.align(.ToTheRightMatchingTop, relativeTo: anchorView, padding: padding, width: size, height: size)
view5.align(.ToTheRightCentered, relativeTo: anchorView, padding: padding, width: size, height: size)
view6.align(.ToTheRightMatchingBottom, relativeTo: anchorView, padding: padding, width: size, height: size)
view7.align(.UnderMatchingRight, relativeTo: anchorView, padding: padding, width: size, height: size)
view8.align(.UnderCentered, relativeTo: anchorView, padding: padding, width: size, height: size)
view9.align(.UnderMatchingLeft, relativeTo: anchorView, padding: padding, width: size, height: size)
view10.align(.ToTheLeftMatchingBottom, relativeTo: anchorView, padding: padding, width: size, height: size)
view11.align(.ToTheLeftCentered, relativeTo: anchorView, padding: padding, width: size, height: size)
view12.align(.ToTheLeftMatchingTop, relativeTo: anchorView, padding: padding, width: size, height: size)

Align

Align and fill

You don't always know or want to specify the size of a view that you want to layout relative to another, but rather you want to either fill the width, height, or the entire rest of the superview, after aligning with the sibling. Combined with all the different alignment types discussed earlier, we're starting to see how more complex layouts can be built very easily:

view2.alignAndFillWidth(align: .ToTheRightMatchingTop, relativeTo: view1, padding: padding, height: size / 2.0)
view4.alignAndFillHeight(align: .AboveCentered, relativeTo: view3, padding: padding, width: size / 2.0)
view6.alignAndFill(align: .ToTheLeftMatchingTop, relativeTo: view5, padding: padding)

Align Fill

Align between

Sometimes you want a view to sit between to other views, filling the space between them. Using alignBetweenHorizontal() and alignBetweenVertical(), doing that is super easy! Choose one of your sibling views you want to align your view relative to and pass that in as your primaryView. We will use the specified align parameter to match that primaryView appropriately, and automatically fill either the horizontal or vertical span between the it and the secondaryView.

view1.alignBetweenHorizontal(align: .ToTheRightMatchingTop, primaryView: anchorViewA, secondaryView: anchorViewB, padding: padding, height: size)
view2.alignBetweenVertical(align: .UnderCentered, primaryView: anchorViewB, secondaryView: anchorViewD, padding: padding, width: size)
view3.alignBetweenHorizontal(align: .ToTheLeftMatchingBottom, primaryView: anchorViewD, secondaryView: anchorViewC, padding: padding, height: size)
view4.alignBetweenVertical(align: .AboveMatchingRight, primaryView: anchorViewC, secondaryView: anchorViewA, padding: padding, width: size)

Align Between Fill

What about labels?

One of the more complicated parts of working with dynamic layouts, is dealing with labels that may have 1 -> n lines, and as such passing in a specific height isn't always possible without causing a migraine. Neon makes this easy by introducing the AutoHeight constant. Pass this value into methods that accept a height param, and we will first set the width of the frame, tell the view to sizeToFit() so the height is automatically set based on its contents, and then align the view appropriately. For example:

testLabel.alignBetweenHorizontal(align: .ToTheRightMatchingBottom, primaryView: anchorViewA, secondaryView: anchorViewB, padding: padding, height: AutoHeight)

Auto Height 1

Note that changing the text to something with more characters still produces the same desired result:

Auto Height 2

It's important to note that the using AutoHeight with something like a CALayer, or passing it in to any of the grouping methods (see below) will have undesired consequences, as it almost doesn't make sense in this context. Use AutoHeight with anything that implements sizeToFit() and you should be OK. The vast majority of cases where you'll want to use this is with UILabel objects.

What if I don't want to align them perfectly?

Sometimes you don't want your views to align with their sibling views exactly - you may want to align them relative to their siblings, but with a slight offset. You can do this by adding the optional offset parameter to any of the above align methods to produce something like the following:

view1.align(.ToTheRightMatchingTop, relativeTo: anchorViewA, padding: padding, width: size, height: size, offset: offset)
view2.align(.UnderMatchingLeft, relativeTo: anchorViewA, padding: padding, width: size, height: size, offset: offset)

Offset

Grouping

Another common use-case is the grouping of sibling views, aligned in a row or column. Using what we've already learned about anchoring views in the center, in a corner, or against an edge, we can also do the same with groups of views!

The primary difference with grouping, is that it is done by the parent view, or superview of a group of views. For example, let's let two different views center a group of their subviews in each of the two different Group configurations, .Horizontal and .Vertical:

anchorViewA.groupInCenter(group: .Horizontal, views: [view1, view2, view3], padding: padding, width: size, height: size)
anchorViewB.groupInCenter(group: .Vertical, views: [view4, view5, view6], padding: padding, width: size, height: size)

Group in center

How about grouping views in the corner?

anchorViewA.groupInCorner(group: .Horizontal, views: [view1, view2, view3], inCorner: .TopLeft, padding: padding, width: size, height: size)
anchorViewB.groupInCorner(group: .Vertical, views: [view4, view5, view6], inCorner: .BottomRight, padding: padding, width: size, height: size)

Group in corner

As you might have expected, you can also group either horizontally and vertically against any edge as well:

anchorViewA.groupAgainstEdge(group: .Horizontal, views: [view1, view2, view3], againstEdge: .Left, padding: padding, width: size, height: size)
anchorViewB.groupAgainstEdge(group: .Vertical, views: [view4, view5, view6], againstEdge: .Bottom, padding: padding, width: size, height: size)

Group against edge

Grouping views relative to a sibling view can be done as well:

view.groupAndAlign(group: .Horizontal, andAlign: .ToTheRightMatchingTop, views: [view1, view2, view3], relativeTo: anchorViewA, padding: padding, width: size, height: size)
view.groupAndAlign(group: .Vertical, andAlign: .UnderCentered, views: [view4, view5, view6], relativeTo: anchorViewA, padding: padding, width: size, height: size)

Group relative

You can also specify that you want a group of subviews to fill their superview, either horizontally or vertically:

anchorViewA.groupAndFill(group: .Horizontal, views: [view1, view2, view3], padding: padding)
anchorViewB.groupAndFill(group: .Vertical, views: [view4, view5, view6], padding: padding)

Group and fill

License

The source is made available under the MIT license. See LICENSE.txt for details.

Comments
  • Update to Swift 3

    Update to Swift 3

    Already noticed a lot of updates are required. I may try to update some of the stuff, but I'm really busy at the moment. What are the plans to update Neon to Swift v3?

    enhancement 
    opened by MatrixSenpai 35
  • How to  autoheight UITableViewCell?

    How to autoheight UITableViewCell?

    When i use Neon,I can't use this gramera to autoHeight UITableViewCell self.tableView.rowHeight = UITableViewAutomaticDimension self.tableView.estimatedRowHeight = 300

    Could you fix the problem? Thank you.

    question 
    opened by Orangerc 10
  • Dynamic UIlabel

    Dynamic UIlabel

    It's not a issue just a suggestion. at the moment I have UILabels that can have 1 to 2 lines depending and text size.

    at the moment I do this like this but I'm sure there is a better way

    let nameLabelHeight = nameLabel.text?.heightWithConstrainedWidth(self.width - 24 - profilePictureImageView.width, font: nameLabel.font)
        if let n = nameLabelHeight where n > 60 {
            nameLabel.alignAndFillWidth(align: .ToTheRightMatchingTop, relativeTo: profilePictureImageView, padding: 8, height: 60)
        } else if let n = nameLabelHeight {
            nameLabel.alignAndFillWidth(align: .ToTheRightMatchingTop, relativeTo: profilePictureImageView, padding: 8, height: n)
        }
    
    enhancement 
    opened by wieseljonas 9
  • Fixed Carthage build error.

    Fixed Carthage build error.

    A recent change in syntax appears to have removed a method that was previously working.

    As such, i've added an alternative implementation to maintain cross-platform compatibility and the build appears to be working fine now.

    Thanks!

    opened by JFKingsley 7
  • Autolayout question

    Autolayout question

    Hey there,

    I was wondering what this is using under the hood? Are we able to "mix and match" auto layout constraints via Storyboard and Neon for some other views?

    Thanks and great job with this!

    opened by jyounus 7
  • Carthage Support / OSX Support merge

    Carthage Support / OSX Support merge

    Hello, Thanks for your framework.

    I make many changes to make it support Carthage and OSX. I moved Folders and Files here and there, Make two new targets in the Xcode Project. Mark many internal methods as public. So now Neon supports Carthage and OSX. (I'm not using Cocoapods and I make some big changes in this branch. So I haven't change the Podspec because I can't)

    Please take a look at this commit and tell me what you think. Thank you.

    opened by remaerd 7
  • error while carthage update

    error while carthage update

    I add the neon to my Cartfile,but while Im run carthage update commond,terminal show an error:

      *** Fetching Neon
      *** Checking out Neon at "v0.0.2"
      *** xcodebuild output can be found in /var/folders/5y/x8t9wb3d1t33b77ckz509p_w0000gn/T/carthage-xcodebuild.JEhAhQ.log
     A shell task failed with exit code 66:
     xcodebuild: error: Scheme NeonMacDemo is not currently configured for the build action.
    
    opened by zixun 6
  • UILabel width

    UILabel width

    Hi,

    Great work on making a super flexible and simple layout framework.

    Any chance you can have tried to have UIButton and UILabel to automatically calculate their widths as per below where the width of a button/label can be calculated from its contents?

    button1.anchorInCornerAndUseWidth(.BottomLeft, xPad: 20, yPad: 20, height: 30) label2.alignAndUseWidth(align: .ToTheRightMatchingTop, relativeTo: button1, padding: 20, height: 30) button3.alignAndFillWidth(align: .ToTheRightMatchingTop, relativeTo: label2, padding: 20, height: 30)

    Thanks for the elegant work, -Tim

    enhancement 
    opened by tim12s 4
  • AsyncDisplayKit

    AsyncDisplayKit

    I saw in some issue in Facebooks ASDK that someone wanted to use Neon with ASDK. They told him it would be difficult to implement but I think its as easy as

    extension ASDisplayNode : Frameable, Anchorable, Alignable, Groupable {
        public var superFrame: CGRect {
            guard let supernode = supernode else {
                return CGRectZero
            }
    
            return supernode.frame
        }
    }
    

    Isn't it?

    opened by zdnk 4
  • 20 lines of code

    20 lines of code

    In the meantime, here's an intentionally convoluted example to show how easy it is to build very complex and dynamic layouts with Neon. The following layout was created with only 20 lines of code.

    Can we see this code? Thanks.

    question 
    opened by cannyboy 4
  • After aligning the UIscrollview, the subview cant be shown and not scrollable

    After aligning the UIscrollview, the subview cant be shown and not scrollable

    Dear Sir,

    Thanks for making this features. They are awesome! Hope more and more people use yours masterpiece. It's very useful. 👍 👍 👍 👍

    However, for the UIscrollview, the subview cant be shown and not scrollable. Do you have any procedures to include the subview of UIscrollview or how to make the scrollview to be scrollable?

    Thanks a lot! Looking forward to hearing from yours :) Best Regards, JC

    help wanted 
    opened by hkapplet1 3
  • Trapping Rainwater repo using Neon..

    Trapping Rainwater repo using Neon..

    I thought Neon would be perfect for the venerable interview question, so i created this repo to manifest an nice solution:

    http://bit.ly/TrappingRainwater

    thank you!

    opened by wdcurry 0
  • Using Neon in a custom view xib?

    Using Neon in a custom view xib?

    I saw one other issue like that (unfortunately with no follow-up by the OP). I am hoping to create a custom nib-based view to drop into a main view, and each instance will manage its own layout via neon (liking the repo!). But, there is absolutely no neon-action within the instantiation. I have the most basic of view, and simply firing it up within the main VC, and dropped a sample view that is instructed to fill its container. I set the colors to show me it works. It does not. Wondering if you have tried something similar?

    opened by wdcurry 0
  • StackFillEdge?

    StackFillEdge?

    Perhaps i am missing this, or perhaps my suggested name is not quite right but my basic use case causes me to introduce container views to achieve my layout. It is similar to building a table row by row: the first view must fill top width, then the next one must fill the next top width below it and so on. Grouping top left than calculating width could work but the adding of the elements can be staggering in time.

    Perhaps this is already easy and I am just missing how? thx..

    Awesome repo btw!!

    opened by wdcurry 0
Releases(v0.4.0)
Owner
Mike
Mike
Concise Auto Layout API to chain programmatic constraints while easily updating existing constraints.

Concise API for Auto Layout. SnapLayout extends UIView and NSView to deliver a list of APIs to improve readability while also shortening constraint co

Satinder Singh 11 Dec 17, 2021
Swifty DSL for programmatic Auto Layout in iOS

WWLayout Easy to write auto layout constraints, with minimal extensions to standard namespaces. Feature Highlights Easy to use, readable API Backwards

WW Tech 49 Oct 2, 2022
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
⚓️ Declarative, extensible, powerful Auto Layout

EasyAnchor ❤️ Support my apps ❤️ Push Hero - pure Swift native macOS application to test push notifications PastePal - Pasteboard, note and shortcut m

Khoa 449 Nov 10, 2022
AppStoreClone - Understanding the complex layout of app store using UICompositional layout in swift

AppStoreClone Understanding the complex layout of app store using UICompositiona

Dheeraj Kumar Sharma 8 Dec 28, 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 custom layout built on top of SwiftUI's Layout API that lays elements out in multiple lines. Similar to flex-wrap in CSS, CollectionViewFlowLayout.

WrapLayout A custom layout built on top of SwiftUI's Layout API that lays elements out in multiple lines. Similar to flex-wrap in CSS, CollectionViewF

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

CGLayout Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Has cross-hierarchy coordinate space. Implemen

Koryttsev Denis 45 Jun 28, 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
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
MyLayout is a simple and easy objective-c framework for iOS view layout

MyLayout is a powerful iOS UI framework implemented by Objective-C. It integrates the functions with Android Layout,iOS AutoLayout,SizeClass, HTML CSS float and flexbox and bootstrap. So you can use LinearLayout,RelativeLayout,FrameLayout,TableLayout,FlowLayout,FloatLayout,PathLayout,GridLayout,LayoutSizeClass to build your App 自动布局 UIView UITableView UICollectionView RTL

欧阳大哥2013 4.2k Dec 30, 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
The most powerful Grid container missed in SwiftUI

Grid Grid view inspired by CSS Grid and written with SwiftUI We are a development agency building phenomenal apps. Overview Grid is a powerful and eas

Exyte 1.2k Jan 2, 2023
BrickKit is a delightful layout library for iOS and tvOS. It is written entirely in Swift!

BrickKit is a delightful layout library for iOS and tvOS. It is written entirely in Swift! Deprecated BrickKit is being phased out at Wayfair, and the

Wayfair Tech – Archive 608 Sep 15, 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
A declarative Auto Layout DSL for Swift :iphone::triangular_ruler:

Cartography ?? ?? Using Cartography, you can set up your Auto Layout constraints in declarative code and without any stringly typing! In short, it all

Robb Böhnke 7.3k Jan 4, 2023
An easy way to create and layout UI components for iOS (Swift version).

Introduction Cupcake is a framework that allow you to easily create and layout UI components for iOS 8.0+. It use chaining syntax and provides some fr

nerdycat 288 Oct 9, 2022