All Projects β†’ el-hoshino β†’ Notautolayout

el-hoshino / Notautolayout

Licence: apache-2.0
Layout your views without Auto Layout constraints, in a much more swifty way.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Notautolayout

Xcglogger
A debug log framework for use in Swift projects. Allows you to log details to the console (and optionally a file), just like you would have with NSLog() or print(), but with additional information, such as the date, function name, filename and line number.
Stars: ✭ 3,710 (+2069.59%)
Mutual labels:  swift-framework, carthage
Koyomi
Simple customizable calendar component in Swift πŸ“†
Stars: ✭ 716 (+318.71%)
Mutual labels:  swift-framework, carthage
Pulltodismiss
You can dismiss modal viewcontroller like Facebook Messenger by pulling scrollview or navigationbar in Swift.
Stars: ✭ 456 (+166.67%)
Mutual labels:  swift-framework, carthage
RangeUISlider
πŸ“± πŸ”΅βž–πŸ”΅ An iOS range selection slider compatible with UIKit and SwiftUI. Developed using autolayout and highly customizable using IBDesignabled and IBInspectable or programmatically. It support also RTL (right to left) languages automatically out of the box.
Stars: ✭ 98 (-42.69%)
Mutual labels:  swift-framework, autolayout
Loadingshimmer
An easy way to add a shimmering effect to any view with just one line of code. It is useful as an unobtrusive loading indicator.
Stars: ✭ 1,180 (+590.06%)
Mutual labels:  swift-framework, carthage
Stevia
πŸƒ Concise Autolayout code
Stars: ✭ 3,182 (+1760.82%)
Mutual labels:  carthage, autolayout
Bluecap
iOS Bluetooth LE framework
Stars: ✭ 669 (+291.23%)
Mutual labels:  swift-framework, carthage
Core Layout
Flexbox & CSS-style Layout in Swift.
Stars: ✭ 215 (+25.73%)
Mutual labels:  carthage, autolayout
Framelayoutkit
FrameLayoutKit is a super fast and easy to use autolayout kit
Stars: ✭ 53 (-69.01%)
Mutual labels:  swift-framework, autolayout
Sketchkit
A lightweight auto-layout DSL library for iOS & tvOS.
Stars: ✭ 40 (-76.61%)
Mutual labels:  carthage, autolayout
STTextView
πŸ“ STTextView is a light-weight library that adds a placeholder to the UITextView.
Stars: ✭ 36 (-78.95%)
Mutual labels:  carthage, swift-framework
Contentful.swift
A delightful Swift interface to Contentful's content delivery API.
Stars: ✭ 132 (-22.81%)
Mutual labels:  swift-framework, carthage
iOSProjects
It's project that contains different applications developed with Swift 5.7 πŸ‘¨β€πŸ’»πŸ‘©πŸΌβ€πŸ’»πŸ§‘πŸΏβ€πŸ’»
Stars: ✭ 122 (-28.65%)
Mutual labels:  carthage, autolayout
Misterfusion
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.
Stars: ✭ 314 (+83.63%)
Mutual labels:  carthage, autolayout
L10n Swift
Localization of the application with ability to change language "on the fly" and support for plural form in any language.
Stars: ✭ 177 (+3.51%)
Mutual labels:  swift-framework, carthage
Swiftinstagram
Instagram API client written in Swift
Stars: ✭ 570 (+233.33%)
Mutual labels:  swift-framework, carthage
Swiftlyext
SwiftlyExt is a collection of useful extensions for Swift 3 standard classes and types πŸš€
Stars: ✭ 31 (-81.87%)
Mutual labels:  swift-framework, carthage
Kvconstraintkit
An Impressive Auto Layout DSL for iOS, tvOS & OSX. & It is written in pure swift.
Stars: ✭ 91 (-46.78%)
Mutual labels:  carthage, autolayout
Pinlayout
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]
Stars: ✭ 1,870 (+993.57%)
Mutual labels:  swift-framework, carthage
Cdmarkdownkit
An extensive Swift framework providing simple and customizable markdown parsing.
Stars: ✭ 158 (-7.6%)
Mutual labels:  carthage

NotAutoLayout

Platform Language Carthage compatible Build Status

IMPORTANT: Deprecated!!

This project is now deprecated because Apple has officially realeased SwiftUI framework, which has a totally different layout engine from UIKit, which means it's not able to use NotAutoLayout in SwiftUI.

In addition, I made this project because I don't like the Auto Layout approach in UIKit. But in SwiftUI, it's much better so I don't have a motivation to maintain this project anymore.

If you have any interest to improve this project, please feel free to fork it :)

-The only1 layout framework that treats layout human-erros2 as a Build-time error-

NotAutoLayout is a framework to help you layout subviews without Auto Layout constraints.

Please note that this framework hasn't been widely tested yet, and currently it's for iOS only.

Please open an issue or send me a pull request if you have any problems, better ideas or any other things you want me to know.

Why NotAutoLayout

Apple introduced Interface Builder and Storyboard to help developers create views visually, which is a very good idea. But after iPhone 5, things changed. There're more and more screen resolutions with different aspect ratios that drives developer crazy. To solve this problem, Apple introduced Auto Layout and Size Classes.

But the problem is, they're just making things more complicated (and that's why they introduced UIStackView and NSGridView, maybe). You have to create dozens of constraints in order to just create a very simple view in the storyboard, which makes the system complicated and hard to debug. In addition, there is no hierarchy for the constraints, which means that you have to manage all those dozens of constraints in one place, which is just not intuitive because we always add many subviews to views, and even more further subviews to subviews, which makes a hierarchy of views.

So, there are some frameworks like Snapkit and PureLayout to help you create Auto Layout constraints much more easily (which should be Xcode's duty). But there are still some old school developers (like me :P) just don't like, or even hate Auto Layout and want to create layout through codes. That's why I created NotAutoLayout framework.

With NotAutoLayout, you don't need to care about anything like constraints or size classes, instead you just need to focus on where is the edge of the element, how big should I resize the element, and maybe what should I do after layout process finished. Every layout process done through NotAutoLayout framework is through directly setting frame property if transform is .identity, or bounds.size and center properties otherwise, which makes it easier to debug than constraints (Yes you can even put a breaker to get the detailed layout information!).

Requirements

  • iOS 9.0+
  • Xcode 10.2+
  • Swift 5.0+

Installation

Use Carthage

github "el-hoshino/NotAutoLayout" ~> 3.3
  • Run carthage update.
  • Add the framework to your project.

Use CocoaPods

  • Download and install CocoaPods.
  • Specify NotAutoLayout in your Podfile like following:
pod 'NotAutoLayout', `~> 3.3`
  • Run pod install.

Manually

  • Download the whole repository.
  • Add the NotAutoLayout project file into your project.
  • Build the framework.

Usage

TL;DR

I wrote a barely practical sample code Playground file, which may help you get the idea. Here's the main source code, and you can find the full sample code inside the project

import PlaygroundSupport
import NotAutoLayout

let controller = IPhoneXScreenController()
controller.rotate(to: .portrait)
PlaygroundPage.current.liveView = controller.view

let appView = LayoutInfoStoredView()
appView.backgroundColor = .white
controller.view.addSubview(appView)

controller.view.nal.layout(appView) { $0
	.stickOnParent()
}

let padding: NotAutoLayout.Float = 10
let summaryView = ProfileSummaryView()
let contentsView = ContentsView()
let replyView = ReplyView()

summaryView.avatar = #imageLiteral(resourceName: "avatar.png")
summaryView.mainTitle = "ζ˜Ÿι‡Žζ΅η‘ οΌ δ»Šζ—₯γ‚‚1ζ—₯γƒ•γƒ¬γƒ³γ‚ΊγŒ "
summaryView.subTitle = "@lovee"
contentsView.contents = """
	Hello, NotAutoLayout!
	The new NotAutoLayout 3.0 now has even better syntax which is:
	- Easy to write (thanks to method-chain structures)
	- Easy to read (thanks to more natural English-like statements)
	- Capable with dynamic view sizes (with commands like `fitSize()`)
	- Even better closure support to help you set various kinds of layouts with various kinds of properties!
	- And one more thing: an experienmental sequencial layout engine!
	"""
contentsView.timeStamp = Date()

appView.nal.setupSubview(summaryView) { $0
	.setDefaultLayout { $0
		.setLeft(by: { $0.layoutMarginsGuide.left })
		.setRight(by: { $0.layoutMarginsGuide.right })
		.setTop(by: { $0.layoutMarginsGuide.top })
		.setHeight(to: 50)
	}
	.addToParent()
}
appView.nal.setupSubview(contentsView) { $0
	.setDefaultLayout({ $0
		.setLeft(by: { $0.layoutMarginsGuide.left })
		.setRight(by: { $0.layoutMarginsGuide.right })
		.pinTop(to: summaryView, with: { $0.bottom + padding })
		.fitHeight()
	})
	.setDefaultOrder(to: 1)
	.addToParent()
}
appView.nal.setupSubview(replyView) { $0
	.setDefaultLayout({ $0
		.setBottomLeft(by: { $0.layoutMarginsGuide.bottomLeft })
		.setRight(by: { $0.layoutMarginsGuide.right })
		.setHeight(to: 30)
	})
	.addToParent()
}

let imageViews = (0 ..< 3).map { (_) -> UIImageView in
	let image = #imageLiteral(resourceName: "avatar.png")
	let view = UIImageView(image: image)
	appView.addSubview(view)
	return view
}


appView.nal.layout(imageViews) { $0
	.setMiddle(by: { $0.vertical(at: 0.7) })
	.fitSize()
	.setHorizontalInsetsEqualingToMargin()
}

screenshot

Tell me more

The fundamental approach of NotAutoLayout is to make a CGRect for each view that can apply to its frame property (or bound.size and center property, in case the transform property is not .identity). There are so many ways to make the CGRect in NotAutoLayout, not only x y width height, you can also specify things like center bottomtLeft middleRight etc.

Basically you have 4 ways to work with NotAutoLayout:

  1. Subclass a UIView (or any other exist UIView's subclass) and override layoutSubviews()
  2. Directly use a LayoutInfoStoredView (which already conforms LayoutInfoStorable protocol)
  3. Subclass LayoutInfoStoredView
  4. Subclass a UIView (or any other exist UIView's subclass) and conform it to LayoutInfoStorable protocol

For the 1st way, all you need is to write your layout code in layoutSubviews() method; for the other 3 ways, you can setup a layout for each view, and the view will handle the layout calculation automatically in layoutSubviews() method so you don't need to override it.

To layout a subview in layoutSubviews() method, you can use code like this:

class MyView: UIView {
	
	let viewA = UIView()
	let viewB = UIView()
	
	override func layoutSubviews() {
		super.layoutSubviews()
		
		self.nal.layout(self.viewA) { $0
			.setTopCenter(by: { $0.topCenter })
			.setWidth(by: { $0.width })
			.fitHeight()
		}
		
		self.nal.layout(self.viewB) { $0
			.pinTopCenter(to: self.viewA, with: { $0.bottomCenter })
			.setWidth(by: { $0.width })
			.fitHeight()
		}
		
	}
	
}

which will first layout viewA's top center to parent's top center (which is MyView's top center), having the same width as its parent (which is MyView), and fit its height automatically, then layout viewB's top center to viewA's top bottom, having the same width as its parent (which is MyView), and fit its height automatically.

To setup the layout for a subview, which the parent must conform LayoutInfoStorable protocol, you can also use code like this:

class ViewController: UIViewController {
	
	private(set) lazy var mainView = LayoutInfoStoredView()
	private(set) lazy var viewA = UIView()
	private(set) lazy var viewB = UIView()
	
	override func loadView() {
		self.mainView.frame = UIScreen.main.bounds
		self.view = self.mainView
	}
	
	override func viewDidLoad() {
		super.viewDidLoad()
		
		self.mainView.nal.setLayout(for: self.viewA) { $0
			.setTopCenter(by: { $0.topCenter })
			.setWidth(by: { $0.width })
			.fitHeight()
		}
		
		self.mainView.nal.setupSubview(self.viewB) { $0
			.setDefaultLayout({ $0
				.pinTopCenter(to: self.viewA, with: { $0.bottomCenter })
				.setWidth(by: { $0.width })
				.fitHeight()
			})
			.setDefaultOrder(to: 1)
		}
		
	}
	
}

which will do the same thing as the code before, and the good thing of this way is that you don't have to subclass a UIView for to make mainView. But since your viewB's layout is based on viewA, you'll need to set viewB's layout order to make sure it'll layout viewB after it layout viewA.

How to make a layout

You may call nal.layout(_ subview: UIView, by making: (_ layoutMaker: LayoutMaker<IndividualProperty.Initial>) -> LayoutMaker<IndividualLayout>) to set a layout for subview from the parent view. The very basic idea is to make layouts through LayoutMakers. With LayoutMaker, you can setup a layout by setting each part of a frame step by step to generate a specific layout, and then the parent view will use the generated layout to set the frame of the subview.

To setup a layout by LayoutMaker, you may call methods like $0.setTopLeft(to: .zero).fitSize() in the provided making closure. Since it's a (LayoutMaker<IndividualProperty.Initial>) -> LayoutMaker<IndividualLayout> type closure, it will guarantee that finally you'll get a specific layout that avoids things like ambiguous layout in Auto Layout. And since LayoutMaker<IndividualProperty.Initial> has lots of chaind methods those lead to a LayoutMaker<IndividualLayout>, you can easily write a method chain without missing any part of a frame.

Theoretically, to make a certain frame you'll need 4 elements: 2 unique horizontal positions and 2 unique vertical positions. Horizontal positions may be any of the things like left, center, right or any specific position like 0.3, and width which also can represent a horizontal position. Vertical positions may be any of the things like top, middle, bottom or any specific position like 0.3, and of course height. Currently, because there're some LayoutPropertys not declared yet, in order to set these elements through LayoutMaker, there is an approximate order that is:

  1. Set point-specific positions (like .setTopLeft) before line-specific positions (like .setTop or .setLeft).
  2. Set line-specific positions before set size elements (.setWidth, .setHeight and .setSize).
  3. In line-specific positions, set horizontal positions (like .setLeft) before vertical positions (like .setTop).

Since you only need 2 unique horizontal positions and 2 unique vertical positions to make a frame, you don't need to write all those 4 categories of statements. For example, you may write $0.setTopLeft(to: .zero).fitSize() to make a specific frame, which only have 2 statements.

And in LayoutMakers, you also have some methods that can get the parent view's size and safe area related properties (like .setLeft(by: { $0.safeAreaGuide.topCenter })), which can help you in making responsive layouts.

How it actually works

NotAutoLayout provides serveral APIs for user to make a specific frame for a subview, like pinTopCenter and many others introduced before. As a developer you only need to care how the designer designed the layout of each subview, and then you just need to translate it into code directly. NotAutoLayout's layout engine will take care of how to make that exact CGRect.

To provide the API to make a frame, NotAutoLayout contains a lot of LayoutPropertys. With these makers, you can easily understand which elements are required to make a specific frame while writing the code, and easily understand what layout the developer wants to achieve through the code. The initializer of these makers are hidden from you developers, so in order to access it you'll need to use code like .nal.layout(aSubView), then you'll get a maker in the following closure, like the sample code in ### Tell me more. The $0 in that sample code is the layout maker. And through those chained mathods like pinTopCenter you'll finally get a LayoutMaker<IndividualLayout> in the closure. When the closure's calculation is finished, NotAutoLayout's layout engine will extract the layout from the IndividualLayout.

Comparison with other layout frameworks

Items NotAutoLayout PinLayout LayoutKit SnapKit PureLayout Cartography
Written in Swift Swift Swift (and a little ObjC) Swift ObjC (and a little Swift) Swift
Based on Pure code Pure code Pure code Auto Layout Auto Layout Auto Layout
Platforms iOS iOS / macOS / tvOS iOS / macOS / tvOS iOS / macOS / tvOS iOS / macOS / tvOS iOS / macOS
Dependency Manager CocoaPods / Carthage CocoaPods / Carthage CocoaPods / Carthage CocoaPods / Carthage CocoaPods / Carthage CocoaPods / Carthage
Performance β—― β—― β—― Γ— Γ— Γ—
Easy to write β—― β—― Γ— β—― β—― β–³3
Easy to read β—― β–³4 β–³5 β—― β—― β—―
Ex-Short syntax Γ— β—― Γ— Γ— Γ— Γ—
Chained methods β—― β—― Γ— β–³6 Γ— Γ—
Targeted extensions7 β—― β—― Γ—8 β—― Γ— Γ—8
Behaviour on human-errors2 Build-time Error Run-time Warning Build-time Error9 Run-time Warning Run-time Warning Run-Time Warning

Known issues

  • [x] Inline documents are not finished yet.
  • [ ] Some LayoutPropertys are not declared yet,
  • [ ] Matrical layout is not implemented yet.

Expects in version 4.0

You may notice that I've made a new framework SteinsKit. In that framework, I've made the structure more refined with bootstrap scripts, Danger implements for better CI runnings, and the most important thing, Sourcery implements for meta programming! These features will join NotAutoLayout in version 4.0!

But the problem is, I don't have an actual plan yet for when exactly to release 4.0. Hopefully I can implement them after WWDC or some time.

License

NotAutoLayout is released under the Apache license. See LICENSE for details.

Notes

  • 1: Maybe. At least I personally haven't found a second one.
  • 2: Things like Ambiguous Layout on Auto Layout, or just forgot to set an edge for a subview while overriding layoutSubviews.
  • 3: It's not difficult to memorize the syntax, but you have to write global functions rather than methods, which makes it a little bit hard for auto-completion comparing with methods.
  • 4: Sometimes the method name is too short to understand what it really does.
  • 5: It's not very difficult to understand, but still takes a while to read the syntax.
  • 6: SnapKit does have chained methods to help you making Auto Layout constraints, but you may still need to write more than one statement to make all required constraints.
  • 7: A namespaced extension making method made like this. One of the famous examples is .rx access control in RxSwift.
  • 8: LayoutKit and Cartography don't have a namespaced extension mechanism, but instead LayoutKit uses local types, and Cartography uses function to avoid possible name-confilictions.
  • 9: LayoutKit theoretically doesn't make any ambiguous layouts within its syntax, but it still produces some implicitly sizing process.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].