FlexLayout
FlexLayout adds a nice Swift interface to the highly optimized facebook/yoga flexbox implementation. Concise, intuitive & chainable syntax.
Install / Use
/learn @layoutBox/FlexLayoutREADME
FlexLayout adds a nice Swift interface to the highly optimized Yoga flexbox implementation. Concise, intuitive & chainable syntax.
Flexbox is an incredible improvement over UIStackView. It is simpler to use, much more versatile and amazingly performant.
Yoga is a multiplatform CSS Flexbox implementation (iOS/Android/...). Yoga is also the layout engine of React Native.
Requirements
- iOS 13.0+
- Xcode 13.0+
- Swift 5.5
Content
- Introduction examples
- FlexLayout principles and philosophy
- Performance
- Documentation
- API Documentation
- Examples App
- FAQ
- Comments, ideas, suggestions, issues, ....
- Installation
:pushpin: FlexLayout is actively updated. So please come often to see latest changes. You can also Star it to be able to retrieve it easily later.
<br>FlexLayout + PinLayout
<a href="https://github.com/layoutBox/PinLayout"><img src="docs_markdown/images/flexlayout_plus_pinlayout_small.png" alt="FlexLayout" width="250"/></a>
FlexLayout is a companion of PinLayout. They share a similar syntax and method names. PinLayout is a layout framework greatly inspired by CSS absolute positioning, it is particularly useful for greater fine control and animations. It gives you full control by layouting one view at a time (simple to code and debug).
- A view can be layouted using FlexLayout, PinLayout, or both!
- PinLayout can layout anything, but in situations where you need to layout many views but don't require PinLayout's finest control nor complex animations, FlexLayout is best fitted.
- A view layouted using PinLayout can be embedded inside a FlexLayout's container and reversely. You choose the best layout framework for your situation.
<a name="intro_usage_example"></a>
FlexLayout Introduction examples
Example 1:
This example will layout multiples views using column and row flexbox containers.
Two steps to use a flexbox container:
- Setup the container: Initialize your flexbox structure. Note that it is also possible to alter it later.
- Layout the container: The layout of the container should be done from
layoutSubviews()(orwillTransition(to: UITraitCollection, ...)andviewWillTransition(to: CGSize, ...)).- First you must layout the flexbox container, i.e. position it and optionally set its size.
- Then layout the flexbox children using Flex method
layout().
<a href="https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/Intro/IntroView.swift"><img src="docs_markdown/images/examples/flexlayout_exampleapp_intro_all.png" alt="FlexLayout example"/></a>
fileprivate let rootFlexContainer = UIView()
init() {
super.init(frame: .zero)
addSubview(rootFlexContainer)
...
// Column container
rootFlexContainer.flex.direction(.column).padding(12).define { (flex) in
// Row container
flex.addItem().direction(.row).define { (flex) in
flex.addItem(imageView).width(100).aspectRatio(of: imageView)
// Column container
flex.addItem().direction(.column).paddingLeft(12).grow(1).define { (flex) in
flex.addItem(segmentedControl).marginBottom(12).grow(1)
flex.addItem(label)
}
}
flex.addItem().height(1).marginTop(12).backgroundColor(.lightGray)
flex.addItem(bottomLabel).marginTop(12)
}
}
override func layoutSubviews() {
super.layoutSubviews()
// 1) Layout the flex container. This example use PinLayout for that purpose, but it could be done
// also by setting the rootFlexContainer's frame:
// rootFlexContainer.frame = CGRect(x: 0, y: 0,
// width: frame.width, height: rootFlexContainer.height)
rootFlexContainer.pin.top().left().width(100%).marginTop(topLayoutGuide)
// 2) Then let the flexbox container layout itself. Here the container's height will be adjusted automatically.
rootFlexContainer.flex.layout(mode: .adjustHeight)
}
:pushpin: This example is available in the Examples App. See complete source code
</br><a name="intro_usage_example_raywenderlich"></a>
Example 2:
The example implements the Ray Wenderlich Yoga Tutorial screen using FlexLayout.
<a href="https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial/RaywenderlichTutorialView.swift"><img src="docs_markdown/images/examples/flexlayout_exampleapp_ray_wenderlich_tutorial.png" width=200/></a>
init() {
...
rootFlexContainer.flex.define { (flex) in
// Image
flex.addItem(episodeImageView).grow(1).backgroundColor(.gray)
// Summary row
flex.addItem().direction(.row).padding(padding).define { (flex) in
flex.addItem(summaryPopularityLabel).grow(1)
flex.addItem().direction(.row).justifyContent(.spaceBetween).grow(2).define { (flex) in
flex.addItem(yearLabel)
flex.addItem(ratingLabel)
flex.addItem(lengthLabel)
}
flex.addItem().width(100).height(1).grow(1)
}
// Title row
flex.addItem().direction(.row).padding(padding).define { (flex) in
flex.addItem(episodeIdLabel)
flex.addItem(episodeTitleLabel).marginLeft(20)
}
// Description section
flex.addItem().paddingHorizontal(paddingHorizontal).define { (flex) in
flex.addItem(descriptionLabel)
flex.addItem(castLabel)
flex.addItem(creatorsLabel)
}
// Action row
flex.addItem().direction(.row).padding(padding).define { (flex) in
flex.addItem(addActionView)
flex.addItem(shareActionView)
}
// Tabs row
flex.addItem().direction(.row).padding(padding).define { (flex) in
flex.addItem(episodesTabView)
flex.addItem(moreTabView)
}
// Shows TableView
flex.addItem(showsTableView).grow(1)
}
}
override func layoutSubviews() {
super.layoutSubviews()
// 1) Layout the contentView & rootFlexContainer using PinLayout
contentView.pin.top().bottom().left().right()
rootFlexContainer.pin.top().left().right()
// 2) Let the flexbox container layout itself and adjust the height
rootFlexContainer.flex.layout(mode: .adjustHeight)
// 3) Adjust the scrollview contentSize
contentView.contentSize = rootFlexContainer.frame.size
}
:pushpin: This example is available in the Examples App. See complete source code
<br><a name="introduction"></a>
FlexLayout principles and philosophy
- Flexbox layouting is simple, powerful and fast.
- FlexLayout syntax is concise and chainable.
- FlexLayout/yoga is incredibly fast, it's even faster than manual layout. See Performance.
- The source code structure matches the flexbox structure, making it easier to understand and modify. Flex containers are defined on one line, and its items (children) are imbricated. This makes the flexbox structure much more visual and easy to understand.
- Supports left-to-right (LTR) and right-to-left (RTL) languages.
NOTE: FlexLayout wraps facebook/yoga implementation and expose all its features. So note that on this documentation we will refer to FlexLayout, but this also applies to Yoga.
<br><a name="performance"></a>
FlexLayout's Performance
FlexLayout's performance has been measured using the Layout Framework Benchmark. FlexLayout and [PinLayout](https
