AsyncDisplayKit

LayoutSpecs

AsyncDisplayKit includes a library of layoutSpec components that can be composed to declaratively specify a layout.

The child(ren) of a layoutSpec may be a node, a layoutSpec or a combination of the two types. In the below image, an ASStackLayoutSpec (vertical) containing a text node and an image node, is wrapped in another ASStackLayoutSpec (horizontal) with another text node.

Both nodes and layoutSpecs conform to the <ASLayoutable> protocol. Any ASLayoutable object may be the child of a layoutSpec. ASLayoutable properties may be applied to ASLayoutable objects to create complex UI designs.

Single Child layoutSpecs

LayoutSpec Description
ASInsetLayoutSpec

Applies an inset margin around a component.

The object that is being inset must have an intrinsic size.

ASOverlayLayoutSpec

Lays out a component, stretching another component on top of it as an overlay.

The underlay object must have an intrinsic size. Additionally, the order in which subnodes are added matters for this layoutSpec; the overlay object must be added as a subnode to the parent node after the underlay object.

ASBackgroundLayoutSpec

Lays out a component, stretching another component behind it as a backdrop.

The foreground object must have an intrinsic size. The order in which subnodes are added matters for this layoutSpec; the background object must be added as a subnode to the parent node before the foreground object.

ASCenterLayoutSpec

Centers a component in the available space.

The ASCenterLayoutSpec must have an intrinisic size.

ASRatioLayoutSpec

Lays out a component at a fixed aspect ratio (which can be scaled).

This spec is great for objects that do not have an intrinisic size, such as ASNetworkImageNodes and ASVideoNodes.

ASRelativeLayoutSpec

Lays out a component and positions it within the layout bounds according to vertical and horizontal positional specifiers. Similar to the “9-part” image areas, a child can be positioned at any of the 4 corners, or the middle of any of the 4 edges, as well as the center.

ASLayoutSpec

Can be used as a spacer in a stack spec with other children, when .flexGrow and/or .flexShrink is applied.

This class can also be subclassed to create custom layout specs - advanced ASDK only!

Multiple Child(ren) layoutSpecs

The following layoutSpecs may contain one or more children.

LayoutSpec Description
ASStackLayoutSpec

Allows you to stack components vertically or horizontally and specify how they should be flexed and aligned to fit in the available space.

This is the most common layoutSpec.

ASStaticLayoutSpec Allows positioning children at fixed offsets using the .sizeRange and .layoutPosition ASLayoutable properties.

ASLayoutable Properties

The following properties can be applied to both nodes and layoutSpecs; both conform to the protocol.

ASStackLayoutable Properties

The following properties may be set on any node or layoutSpecs, but will only apply to those who are a child of a stack layoutSpec.

Property Description
CGFloat .spacingBefore Additional space to place before this object in the stacking direction.
CGFloat .spacingAfter Additional space to place after this object in the stacking direction.
BOOL .flexGrow If the sum of childrens' stack dimensions is less than the minimum size, should this object grow? Used when attached to a stack layout.
BOOL .flexShrink If the sum of childrens' stack dimensions is greater than the maximum size, should this object shrink? Used when attached to a stack layout.
ASRelativeDimension .flexBasis Specifies the initial size for this object, in the stack dimension (horizontal or vertical), before the flexGrow or flexShrink properties are applied and the remaining space is distributed.
ASStackLayoutAlignSelf alignSelf Orientation of the object along cross axis, overriding alignItems. Used when attached to a stack layout.
CGFloat .ascender Used for baseline alignment. The distance from the top of the object to its baseline.
CGFloat .descender Used for baseline alignment. The distance from the baseline of the object to its bottom.

ASStaticLayoutable Properties

The following properties may be set on any node or layoutSpecs, but will only apply to those who are a child of a static layoutSpec.

Property Description
.sizeRange If specified, the child's size is restricted according to this `ASRelativeSizeRange`. Percentages are resolved relative to the static layout spec.
.layoutPosition The `CGPoint` position of this object within its parent spec.

Providing Intrinsic Sizes for Leaf Nodes

AsyncDisplayKit’s layout is recursive, starting at the layoutSpec returned from layoutSpecThatFits: and proceeding down until it reaches the leaf nodes included in any nested layoutSpecs.

Some leaf nodes provide their own intrinsic size, such as ASTextNode or ASImageNode. An attributed string or an image have their own sizes. Other leaf nodes require an intrinsic size to be set.

Nodes that require the developer to provide an intrinsic size:

To provide an intrinisc size for these nodes, you can set one of the following:

  1. implement calculateSizeThatFits: for custom ASDisplayNode subclasses only.
  2. set .preferredFrameSize
  3. set .sizeRange for children of static nodes only.

Note that .preferredFrameSize is not considered by ASTextNodes. Also, setting .sizeRange on a node will override the node’s intrinisic size provided by calculateSizeThatFits:.

Common Confusions

There are two main confusions that developers have when using layoutSpecs

  1. Certain ASLayoutable properties only apply to children of stack nodes, while other properties only apply to children of static nodes. All ASLayoutable properties can be applied to any node or layoutSpec, however certain properties will only take effect depending on the type of the parent layoutSpec they are wrapped in. These differences are highlighted above in the ASStackLayoutable Properties and ASStaticLayoutable Properties sections.
  2. Have I set an intrinsic size for all of my leaf nodes?

I set .flexGrow on my node, but it doesn’t grow?

Upward propogation of ASLayoutable properties is currently disabled. Thus, in certain situations, the .flexGrow property must be manually applied to the containers. Two common examples of this that we see include:

I want to provide a size for my image, but I don’t want to hard code the size.

Why won’t my stack spec span the full width?

Difference between ASInsetLayoutSpec and ASOverlayLayoutSpec

An overlay spec requires the underlay object (object to which the overlay item will be applied) to have an intrinsic size. It will center the overlay object in the middle of this area.

An inset spec requires its object to have an intrinsic size. It adds the inset padding to this size to calculate the final size of the inset spec.

Best Practices

Edit on GitHub