Fast StackView, Concise syntax, intuitive, readable & chainable. Stacks easily many views horizontally or vertically. Greatly inspired by Flexbox.
- StackView can be used with manual layout, Autolayout and Storyboards/XIB.
- Compare to UIStackView, StackView is a real UIView, it layout all sub-views from
UIView.subviews
, noUIStackView.arrangedSubviews
. This give you access to backgroundColor, transparency, round corners, animations, transforms, ... - StackView's items can be layouted using one of the 48 positions.
- Margins can be applied on each item individually, giving you full control.
- Width, height, min/max width and min/max height can be applied on each items.
- An aspect ratio can applied on items, particularly useful for images.
- Paddings can be applied to the StackView.
- iOS 9.0+ / tvOS 9.0+
- Xcode 8.0+ / Xcode 9.0
- Swift 3.0+ / Swift 4.0
- Introduction examples
- StackViewLayout principles and philosophy
- Performance
- Documentation
- API Documentation
- Examples App
- FAQ
- Comments, ideas, suggestions, issues, ....
- Installation
📌 StackViewLayout is actively updated. So please come often to see latest changes. You can also Star it to be able to retrieve it easily later.
Three layout frameworks to rule them all:
- StackViewLayout: Stack easily views horizontally or vertically.
- PinLayout: PinLayout is a layout framework greatly inspired by CSS absolute positioning, it is particularly useful for greater fine control and animations, and works perfectly with StactViews. It gives you full control by layouting one view at a time (simple to code and debug).
- FlexLayout: FlexLayout is a full-blown flexbox implementation. Use the same engine as ReactNative.
They all share a similar syntax and method names. Also...
- A view can be layouted using one or many of these frameworks.
- A view layouted using one framework can be embedded inside a view layouted using other frameworks. You choose the best layout framework for your situation.
You: I would like to display 4 buttons horizontally using a StackView. These buttons contains an image. Answer: Easy, just adds these buttons (items) using either addItem(:UIView)
or addSubviews
. StackView layout all views from its UIView.subviews
array. And set the direction to .row
using direction(:Direction)
stackView.direction(.row).define { (stackView) in
stackView.addItem(button1) // or stackView.addSubviews(button1)
stackView.addItem(button2) // or stackView.addSubviews(button2)
stackView.addItem(button3) // or stackView.addSubviews(button3)
stackView.addItem(button4) // or stackView.addSubviews(button4)
}
Result:
You: Nice, but how can we add some margins between items?
Answer: You can set item's margin using margins methods.
stackView.direction(.row).define { (stackView) in
stackView.addItem(button1)
stackView.addItem(button2).marginLeft(10)
stackView.addItem(button3).marginLeft(10)
stackView.addItem(button4).marginLeft(10)
}
Result:
You: Good, but how can we distribute the remaining space around items?
Answer: You can use StackView's method justifyContent(:)
to distribute extra free space.
stackView.direction(.row).justifyContent(.spaceBetween).define { (stackView) in
stackView.addItem(button1)
stackView.addItem(button2).marginLeft(10)
stackView.addItem(button3).marginLeft(10)
stackView.addItem(button4).marginLeft(10)
}
Result:
You: But what if the available screen width available is too narrow to display the 4 buttons?
Result:
You: Oups, buttons overflow on each other, what can we do to fix it?
Answer: You need to specify which items should shrink and in which ratio using shrink(:CGFloat)
. Here we want all buttons to shrink equally, so we use the same shrink factor on all items.
stackView.direction(.row).justifyContent(.spaceBetween).define { (stackView) in
stackView.addItem(button1).shrink(1)
stackView.addItem(button2).marginLeft(10).shrink(1)
stackView.addItem(button3).marginLeft(10).shrink(1)
stackView.addItem(button4).marginLeft(10).shrink(1)
}
Result:
You: Ahh, much better, but buttons aspect ratio is not right, how can we fix that?
Answer: You can specify the aspectRatio for each items using aspectRatio methods.
stackView.direction(.row).justifyContent(.spaceBetween).define { (stackView) in
stackView.addItem(button1).shrink(1).aspectRatio(imageRatio)
stackView.addItem(button2).marginLeft(10).shrink(1).aspectRatio(imageRatio)
stackView.addItem(button3).marginLeft(10).shrink(1).aspectRatio(imageRatio)
stackView.addItem(button4).marginLeft(10).shrink(1).aspectRatio(imageRatio)
}
Result:
You: Perfect! Now suppose I want a second row of buttons. Answer:
You: Perfect! Now we have buttons that layout correctly on any screen size!
Complete source code:
fileprivate let stackView = StackView()
init() {
super.init(frame: .zero)
stackView.direction(.row).justifyContent(.spaceBetween).define { (stackView) in
stackView.addItem(button1).shrink(1).aspectRatio(imageRatio)
stackView.addItem(button2).marginLeft(10).shrink(1).aspectRatio(imageRatio)
stackView.addItem(button3).marginLeft(10).shrink(1).aspectRatio(imageRatio)
stackView.addItem(button4).marginLeft(10).shrink(1).aspectRatio(imageRatio)
}
addSubview(stackView)
}
override func layoutSubviews() {
super.layoutSubviews()
// Layout the StackView. This example use PinLayout for that purpose, but it could be done
// also by setting the StackView's frame or using autolayout.
stackView.pin.top(safeArea.top).horizontally(10).sizeToFit(.width)
}
📌 This example is available in the Examples App. See complete source code
- StackViewLayout layouting is simple, powerful and fast.
- StackViewLayout syntax is concise and chainable.
- StackViewLayout share the same exact API as FlexLayout. But its usage is easier in most situations.
- StackViewLayout is incredibly fast compared to UIStackView. See Performance.
- Fine items spacing adjustment using margins.
- Not intrusive. StackViewLayout only adds one property to existing iOS classes:
UIView.item
. - Method's name match PinLayout and FlexLayout.
- StackView inherits from UIView, so it supports all visual tweaks, including backgroundColor, layer borders, round corners, animations, .... Which is not the case for UIStackView.
- StackView doesn't have an internal list of items (as
UIStackView.arrangedSubviews
), it simply layout all views from itsUIView.subviews
array.
TO BE DOCUMENTED
The defining aspect of StackView is the ability to alter its items, width, height to best fill the available space on any display device. A StackView expands its items to fill the available free space or shrinks them to prevent overflow.
The StackViewLayout is constituted of the StackView
class and its immediate children which are called items.
When working with StackViews you need to think in terms of two axes — the main axis and the cross axis. The main axis is defined by StackView's direction
property, and the cross axis runs perpendicular to it.
StackView direction | Axes |
---|---|
column | ![]() |
row | ![]() |
In the following sections we will see:
- StackView class
- How to layout StackViews
- Managing StackView's items
- StackView properties
- Items properties
TODO: 📌 This document is a guide that explains how to use StackViewLayout. You can also checks the StackViewLayout API documentation.
- StackView class inherits from UIView:
- So, it can be added has a subview and layouted has any other UIView.
- It also means it supports all visual tweaks, including backgroundColor, layer borders, rounded corners, .... Which is not the case for an UIStackView.
- StackView doesn't have an internal list of items (as
UIStackView.arrangedSubviews
), it simply layout all views from itsUIView.subviews
array. - StackView layout all visible views (
isHidden = false
) from itsUIView.subviews
array.
When you use a StackView, you are responsible for the layout (position and size) of the StackView in its container (superview). Then, the StackView manages the layout and size of its content. Views contained in the StackView are called items.
StackView attempts to fill the space along the main-axis with its items. It sizes each item via its sizeThatFits returned value and if there is a leftover or a lack of space, it uses item's grow
and shrink
properties to determine which items to grow or shrink. StackView also takes into account item's margins. See grow and shrink properties for more details.
private let stackview = StackView()
init() {
super.init(frame: .zero)
stackview.define { (stack) in
stack.addItem(button1)
stack.addItem(button2)
}
addSubView(stackView)
}
override func layoutSubviews() {
super.layoutSubviews()
stackView.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
}
This section explain how to control the size of a StackView and how it is possible to adjust the StackView's size to match its items.
You must define at least one dimension (width or height) to layout a StackView.
Two options when layouting StackView:
- Fixed size
- StackView adjust its size to match its items
StackView's size can be set to a specific width and height, in this situation the StackView will adjust the size and the position of all its items to fill the available space. You can control how items are layouted using StackView's properties and item's properties.
StackView should be layouted either from UIView.layoutSubviews()
or UIViewController.viewWillLayoutSubviews()
.
In this example the StackView will be layouted to fill completely its parent.
Using PinLayout:
init() {
...
stackview.define { (stack) in
stack.addItem(button1)
stack.addItem(button2).marginTop(10)
stack.addItem(button3).marginTop(10)
}
addSubView(stackView)
}
override func layoutSubviews() {
super.layoutSubviews()
stackView.pin.all()
}
Using UIView.frame
property:
override func layoutSubviews() {
super.layoutSubviews()
stackView.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
}
Result:
StackView can be layouted by specifying only one dimension and letting the StackView compute the other dimension. In this situation StackLayout set its dimension to fit all its items.
📌 If the StackView adjust its size to match its items, the justifyContent
property will have no effect.
This example layout a StackView at the top and fill the parent horizontally. The StackView's height will be computed to fit nicely its items. Here is the result:
Using PinLayout:
override func layoutSubviews() {
super.layoutSubviews()
// Use PinLayout sizeToFit(.width) method to adjust the StackView's size.
stackView.pin.top().left().width(100%).sizeToFit(.width)
}
Using UIView.frame
property:
override func layoutSubviews() {
super.layoutSubviews()
let adjustedSize = stackView.sizeThatFits(CGSize(width: frame.width,
height: .greatestFiniteMagnitude))
stackView.frame = CGRect(x: 0, y: 0, width: adjustedSize.width, height: adjustedSize.height)
}
Result: The StackView height as been adjusted to contain all its items.
- Applies to:
StackView
- Returns: StackItem interface of the newly added item.
StackView layout all visible views (isHidden = false
) in the UIView.subviews
array.
Here is the list methods to add or insert items to a StackView.
📌 Since StackView layout all views in the UIView.subviews
array, it is also possible to add or insert views using:
addSubview(_ view: UIView)
insertSubview(_ view: UIView, at index: Int)
insertSubview(_ view: UIView, aboveSubview: UIView)
insertSubview(_ view: UIView, belowSubview: UIView)
Methods:
addItem(_: UIView) -> StackItem
This method adds an item (UIView) to a StackView. The item is added as the last item. Internally this method adds the UIView as a subview. Note that you can also use.insertItem(_ view: UIView, at index: Int) -> StackItem
This method adds an item (UIView) at the specified index. Note that you can also useinsertSubview(_ view: UIView, at index: Int)
.insertItem(_ view: UIView, before refItem: UIView) -> StackItem?
This method adds an item (UIView) before the specified reference item. Note that you can also useinsertSubview(_ view: UIView, aboveSubview: UIView)
.insertItem(_ view: UIView, after refItem: UIView) -> StackItem?
This method adds an item (UIView) after the specified reference item. Note that you can also useinsertSubview(_ view: UIView, belowSubview: UIView)
.
stackview.addItem(imageView)
stackview.addItem(titleLabel, after: imageView)
TODO: Document addStackView()
- Applies to:
StackView
Method:
removeItem(_ view: UIView)
Removes the specified item from the StackView. You can also use the view'sUIView.removeFromSuperview()
method to achieve the exact same result. This method just exist to be consistent withaddItem(:UIView)
.
stackview.removeItem(descriptionLabel)
// Or, you can also use:
descriptionLabel.removeFromSuperview()
- Applies to:
StackView
Method:
define(_ closure: (_ stackView: StackView) -> Void)
This method is used to structure your code so that it matches the view structure. The method has a closure parameter with a single parameter calledstackView
. This parameter is in fact the StackView instance.
stackview.define { (stack) in
stack.addItem(imageView)
stack.addItem(nameLabel)
stack.addItem(descriptionLabel)
}
The same results can also be obtained without using the define()
method.
stackview.addItem(imageView)
stackview.addItem(nameLabel)
stackview.addItem(descriptionLabel)
Advantages of using define()
:
- The source code structure matches the views structure, making it easier to understand and modify.
- Changing an item order, it's just moving up/down its line/block that defines it.
- Moving an item from one StackView to another is just moving line/block that defines it.
This section describes StackView properties that affect how items are layouted.
- Applies to:
StackView
- Values:
column
/row
- Default value:
column
- Method:
direction(_: SDirection)
The direction
property establishes the main-axis, thus defining the direction items are placed in the StackView.
Value | Result | Description |
---|---|---|
column (default) | ![]() | Top to bottom |
row | ![]() | Same as text direction |
📌 IMPORTANT NOTE: StackViewLayout determine items width by calling each item's sizeThatFits(:CGSize)
method with the available width. This is particularly important to understand when using the .row
direction, because in this direction there's a good chance that items will overflow their StackView. In these situations you'll have to use item's shrink
property to fit items inside their StackView.
stackView.direction(.column) // Not required, default value.
stackView.direction(.row)
This example show a StackView of size 300x400 containing three buttons with a margin of 10 pixels between them.
stackView.define { (stack) in
stack.addItem(button1)
stack.addItem(button2).marginTop(10)
stack.addItem(button3).marginTop(10)
}
override func layoutSubviews() {
super.layoutSubviews()
stackView.width(300).height(400)
}
Buttons are stretched horizontally because StackView's default alignItems
property is .stretch
. Also, we don't need to set the direction
since the default value is .column
.
Using the same setup as the Example 1, but using the .row
direction.
stackview.direction(.row).define { (stack) in
stack.addItem(button1)
stack.addItem(button2).marginTop(10)
stack.addItem(button3).marginTop(10)
}
Not really the expected result, right?! Two issues:
Buttons are too tall: By default StackView
alignItems
property is set to.stretch
, which cause items to stretch in the cross axis direction. To fix that, two possible solutions:- Set the
alignItems
property to.start
. SeealignItems
. - Adjust the StackView's height to match its items. See Adjusting size to match its items.
- Set the
Buttons overflow the StackView: The reason for this is that the size of the three buttons + margins are wider than the specified StackView's width (300 pixels). To contain buttons inside the StackView, we can increase the StackView's width OR we must allow items to shrink if there is not enough available space. By default item don't shrink. To enable this we must set the item's
shrink
property. We want that all buttons shrink equitably, so we set each button the sameshrink
property. Seeshrink
for more details.
stackView.direction(.row).alignItems(.start).define { (stack) in
stack.addItem(button1).shrink(1)
stack.addItem(button2).marginLeft(10).shrink(1)
stack.addItem(button3).marginLeft(10).shrink(1)
}
Much better!
Applies to:
StackView
Values:
start
/end
/center
/spaceBetween
/spaceAround
/spaceEvenly
Default value:
start
Method:
justifyContent(_: JustifyContent)
The
justifyContent
property defines the alignment along the main-axis. It helps distribute extra free space leftover when either all items have reached their maximum size. For example, for a column StackView,justifyContent
controls how items align vertically.
This property is similar to UIStackView.distribution
(UIStackViewDistribution)
stackView.justifyContent(.start) // default value.
stackView.justifyContent(.center)
TODO: Add an example!!!
- Applies to:
StackView
- Values:
stretch
/start
/end
/center
- Default value:
stretch
- Method:
alignItems(_: AlignItems)
The alignItems
property defines how items are laid out along the cross axis. Similar to justifyContent
but for the cross-axis (perpendicular to the main-axis). For example, for a column StackView, alignItems
controls how they align horizontally.
This property is similar to UIStackView.alignment
(UIStackViewAlignment)
direction(.column) | direction(.row) | |
---|---|---|
stretch (default) | ![]() | ![]() |
start | ![]() | ![]() |
end | ![]() | ![]() |
center | ![]() | ![]() |
TODO: Add an example!!!
This section describes all StackView's item properties.
- Values:
auto
/stretch
/start
/end
/center
- Default value:
auto
- method:
alignSelf(_: AlignSelf)
The alignSelf
property controls how an item aligns in the cross direction, overriding the alignItems
of the StackView. For example, for a column StackView, alignSelf
will control how the item will align horizontally.
The auto
value means use the stack view alignItems
property. See alignItems
for documentation of the other values.
TODO: Add an example!!!
- Default value: 0
- method:
grow(_: CGFloat)
The grow
property defines the ability for an item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the StackView the item should take up.
A grow
value of 0 (default value) keeps the view's size in the main-axis direction. If you want the view to use the available space set a grow
value > 0.
For example, if all items have grow
set to 1, every child will grow to an equal size inside the container. If you were to give one of the children a value of 2, that child would take up twice as much space as the others.
TODO: Add an example!!!
- Default value: 0
- Method:
shrink(_: CGFloat)
The shrink
defines how much the item will shrink relative to the rest of items in the StackView when there isn't enough space on the main-axis.
A shrink value of 0 keeps the view's size in the main-axis direction. Note that this may cause the view to overflow its flex container.
Shrink is about proportions. If an item has a shrink of 3, and the rest have a shrink of 1, the item will shrink 3x as fast as the rest.
TODO: Add an example!!!
- Method:
markDirty()
- Applies to StackView and items
StackView's items are layouted only when an item's property is changed and when the StackView size change. In the event that you want to force the StackView to update the layout of all its items, you can mark the StackView or any of it's item as dirty using markDirty()
.
Marking an item as dirty will propagates to the direct StackView and all other parents StackViews. So if you update multiple items, calling markDirty()
only on one item or calling it on their StackView have the same effect, the StackView will be re-layouted.
In the case where a UILabel's text is updated, it is needed to mark the label as dirty.
// Update UILabel's text and mark the UILabel as dirty
label.text = "I love StackViewLayout"
label.item.markDirty()
stackView.markDirty()
TODO: Add an example?
StackView's items size can be set manually using the following methods.
📌 Note that if the width/height/size is set and the item's shrink
or grow
property have a value > 0, than if required the item may shrink or grow. Shrink and grow properties have an higher priority than width/height/size.
Methods:
width(_ width: CGFloat?)
The value specifies the view's width in pixels. The value must be non-negative. Callwidth(nil)
to reset the property.width(_ percent: SPercent)
The value specifies the view's width in percentage of its container width. The value must be non-negative. Callwidth(nil)
to reset the property.height(_ height: CGFloat?)
The value specifies the view's height in pixels. The value must be non-negative. Callheight(nil)
to reset the property.height(_ percent: SPercent)
The value specifies the view's height in percentage of its container height. The value must be non-negative. Callheight(nil)
to reset the property.size(_ size: CGSize?)
The value specifies view's width and the height in pixels. Values must be non-negative. Callsize(nil)
to reset the property.size(_ sideLength: CGFloat?)
The value specifies the width and the height in pixels, creating a square view. Values must be non-negative. Callsize(nil)
to reset the property.
view.item.width(100)
view.item.width(50%)
view.item.height(200)
view.item.size(250)
TODO: Add an example!!!
StackView's items min/max width and min/max height can be specified.
Using minWidth, minHeight, maxWidth, and maxHeight gives you increased control over the final size of items. By mixing these properties with grow
, shrink
, and alignItems(.stretch)
, you are able to have items with dynamic size within a range which you control.
An example of when Max properties can be useful is if you are using alignItems(.stretch)
but you know that your item won’t look good after it increases past a certain point. In this case, your item will stretch to the size of its parent or until it is as big as specified in the Max property.
Same goes for the Min properties when using shrink
. For example, you may want an item to shrink, but if you specify a minimum width, the item won't be shrink past the specified value.
Another case where Min and Max dimension constraints are useful is when using aspectRatio
.
Methods:
minWidth(_ width: CGFloat?)
The value specifies the view's minimum width in pixels. The value must be non-negative. CallminWidth(nil)
to reset the property.minWidth(_ percent: SPercent)
The value specifies the view's minimum width of the view in percentage of its container width. The value must be non-negative. CallminWidth(nil)
to reset the property..maxWidth(_ width: CGFloat?)
The value specifies the view's maximum width in pixels. The value must be non-negative. CallmaxWidth(nil)
to reset the property.maxWidth(_ percent: SPercent)
The value specifies the view's maximum width of the view in percentage of its container width. The value must be non-negative. CallmaxWidth(nil)
to reset the property.minHeight(_ height: CGFloat?)
The value specifies the view's minimum height in pixels. The value must be non-negative. CallminHeight(nil)
to reset the property.minHeight(_ percent: SPercent)
The value specifies the view's minimum height of the view in percentage of its container height. The value must be non-negative. CallminHeight(nil)
to reset the property.maxHeight(_ height: CGFloat?)
The value specifies the view's maximum height in pixels. The value must be non-negative. CallmaxHeight(nil)
to reset the property.maxHeight(_ percent: SPercent)
The value specifies the view's maximum height of the view in percentage of its container height. The value must be non-negative. CallmaxHeight(nil)
to reset the property.
view.item.maxWidth(200)
view.item.maxWidth(50%)
view.item.width(of: view1).maxWidth(250)
view.item.maxHeight(100)
view.item.height(of: view1).maxHeight(30%)
TODO: Add an example!!!
By applying Margin to an item you specify the offset a certain edge of the item should have from it’s closest sibling or parent (StackView).
Methods:
marginTop(_ value: CGFloat)
,marginTop(_ percent: FPercent)
Specify the offset the top edge of the item should have from it’s closest sibling (item) or parent (StackView).marginLeft(_ value: CGFloat)
,marginLeft(_ percent: FPercent)
Specify the offset the left edge of the item should have from it’s closest sibling (item) or parent (StackView).marginBottom(_ value: CGFloat)
,marginBottom(_ percent: FPercent)
Specify the offset the bottom edge of the item should have from it’s closest sibling (item) or parent (StackView)marginRight(_ value: CGFloat)
,marginRight(_ percent: FPercent)
Specify the offset the right edge of the item should have from it’s closest sibling (item) or parent (StackView).marginStart(_ value: CGFloat)
,marginStart(_ percent: FPercent)
Set the start margin. In LTR direction, start margin specify the left margin. In RTL direction, start margin specify the right margin.marginEnd(_ value: CGFloat)
,marginEnd(_ percent: FPercent)
Set the end margin. In LTR direction, end margin specify the right margin. In RTL direction, end margin specify the left margin.marginHorizontal(_ value: CGFloat)
,marginHorizontal(_ percent: FPercent)
Set the left, right, start and end margins to the specified value.marginVertical(_ value: CGFloat)
,marginVertical(_ percent: FPercent)
Set the top and bottom margins to the specified value.margin(_ insets: UIEdgeInsets)
Set all margins using an UIEdgeInsets. This method is particularly useful to set all margins using iOS 11UIView.safeAreaInsets
.margin(_ insets: NSDirectionalEdgeInsets)
Set all margins using an NSDirectionalEdgeInsets. This method is useful to set all margins using iOS 11UIView. directionalLayoutMargins
when layouting a view supporting RTL/LTR languages.margin(_ value: CGFloat)
Set all margins to the specified value.margin(_ vertical: CGFloat, _ horizontal: CGFloat)
margin(_ top: CGFloat, _ horizontal: CGFloat, _ bottom: CGFloat)
margin(_ top: CGFloat, _ left: CGFloat, _ bottom: CGFloat, _ right: CGFloat)
view.item.margin(20)
view.item.marginTop(20%).marginLeft(20%)
view.item.marginHorizontal(20)
view.item.margin(safeAreaInsets)
view.item.margin(10, 12, 0, 12)
// Margin is defined inline
stackview.addItem(separatorView).margin(20)
AspectRatio property solves the problem of knowing one dimension of an element and an aspect ratio, this is very common when it comes to images, videos, and other media types. AspectRatio accepts any floating point value > 0, the default is undefined.
- AspectRatio is defined as the ratio between the width and the height of a node e.g. if an item has an aspect ratio of 2 then its width is twice the size of its height.
- AspectRatio respects the Min and Max dimensions of an item.
- AspectRatio has higher priority than
grow
. - If AspectRatio, Width, and Height are set then the cross dimension is overridden.
- Call
aspectRatio(nil)
to reset the property.
Methods:
aspectRatio(: CGFloat)
:
Set the item's aspect ratio using a CGFloat. AspectRatio is defined as the ratio between the width and the height (width / height).aspectRatio()
:
If the layouted view is an UIImageView, this method will set the aspectRatio using the UIImageView's image dimension. For other types of views, this method as no impact.
imageView.flex.aspectRatio(16/9)
- Method:
isIncludedInLayout(: Bool)
- Property:
isIncludedInLayout: Bool
isIncludedInLayout: Bool
/isIncludedInLayout(_ value: Bool)
This property controls dynamically if a StackView's item is included or not in the StackView layouting. When an item is excluded, StackView won't layout the view. Default value is true.
This can be useful if you want to layout an item manually instead of using StackView layouting.
label.item.isIncludedInLayout = false
StackViewLayout also adds methods to set common UIView properties. These methods are available on StackView's instances and on items.
Methods:
backgroundColor(_ color: UIColor)
Set the StackView or item's UIView background color.alpha(_ value: CGFloat)
Set the StackView or item'salpha
property to adjust the transparency.
// Create a gray column StackView and add a black horizontal line separator
stackView.addStackView().backgroundColor(.gray).define { (stackView) in
stackView.addItem(UIView()).height(1).backgroundColor(.black).alpha(0.7)
}
TODO: If you run into situations where multiple elements need to be arranged along multiple axes, UIStackViews can be nested inside each other. Below is the layout from the example project. Each property UILabel and UISegmentedControl are contained in a UIStackView. All of the UIStackViews are then contained in a parent UIStackView denoted on the left.
See addStackView()
This table resume StackView's default properties:
Property | StackView default value |
---|---|
direction | .column |
justifyContent | .start |
alignItems | .stretch |
This table resume Items default properties:
Property | Items default value |
---|---|
alignSelf | .auto |
grow | 0 |
shrink | 0 |
StackView can be also be used with autolayout.
So it is compatible with Storyboards and NIBs.
To use StackView in a Storyboard:
- From Interface builder:
- Add a UIView into your view controller's view.
- Set the view's class to
StackView
:
```swift
stackView.justifyContent(.spaceAround).alignItems(.center)
```
- You can also set the StackView's items properties from source code, simply add reference to them and customize them from source code.
See the example "Autolayout" in the Example App for a complete example.
- Finer control: You can control each item's margin individually (horizontally and vertically). No more needs of adding filler UIViews to add margin between items.
- More control over how items are layouted.
- Can be layouted using autolayout or not, you're not stuck with a single layout framework. StackView can be layouted with any layout frameworks!
- Top and bottom margins using percentages
- StackViewLayout resolve percentages in marginTop and marginBottom against the height of the container.
- FlexLayout/flexbox resolve percentages in marginTop and marginBottom against the width of the container.
The complete StackViewLayout API is available here.
NOT IMPLEMENTED YET. COMING SOON.
- Layout Modes: Display all StackView's layout modes (direction, justifyContent, alignItems)
- CollectionViewExample
- TableViewExample
- Autolayout
COMING SOON.
For any comments, ideas, suggestions, simply open an issue.
For issues, please have a look at Yoga's issues. Your issue may have been already reported. If not, it may be a StackViewLayout issue. In this case open an issue and we'll let you know if the issue is related to Yoga's implementation.
If you find StackViewLayout interesting, thanks to Star it. You'll be able to retrieve it easily later.
If you'd like to contribute, you're welcome!
To integrate StackLayoutView into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'StackLayoutView'
Then, run pod install
.
NOT IMPLEMENTED YET. COMING SOON.
NOT IMPLEMENTED YET. COMING SOON.
List of features that will be implement soon:
- Add aspect ratio support
- RTL (right-to-left) language support
- Implement distribution mode as UIStackView (.fill, FillEqually, FillProportionally, ...)
- Implement directions row-reverse and column-reverse
- Support StackView padding
StackViewLayout recent history is available in the are documented in the CHANGELOG.
BSD 3-Clause License