Swiftgram/submodules/AsyncDisplayKit/docs/_docs/automatic-layout-examples-2.md
Peter 9bc996374f Add 'submodules/AsyncDisplayKit/' from commit '02bedc12816e251ad71777f9d2578329b6d2bef6'
git-subtree-dir: submodules/AsyncDisplayKit
git-subtree-mainline: d06f423e0ed3df1fed9bd10d79ee312a9179b632
git-subtree-split: 02bedc12816e251ad71777f9d2578329b6d2bef6
2019-06-11 18:42:43 +01:00

10 KiB
Executable File

title layout permalink prevPage nextPage
Layout Examples docs /docs/automatic-layout-examples-2.html layout2-quickstart.html layout2-layoutspec-types.html

Check out the layout specs example project to play around with the code below.

Simple Header with Left and Right Justified Text

To create this layout, we will use a:

  • a vertical ASStackLayoutSpec
  • a horizontal ASStackLayoutSpec
  • ASInsetLayoutSpec to inset the entire header

The diagram below shows the composition of the layout elements (nodes + layout specs).

Swift Objective-C
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
  // when the username / location text is too long, 
  // shrink the stack to fit onscreen rather than push content to the right, offscreen
  ASStackLayoutSpec *nameLocationStack = [ASStackLayoutSpec verticalStackLayoutSpec];
  nameLocationStack.style.flexShrink = 1.0;
  nameLocationStack.style.flexGrow = 1.0;

// if fetching post location data from server, // check if it is available yet and include it if so if (_postLocationNode.attributedText) { nameLocationStack.children = @[_usernameNode, _postLocationNode]; } else { nameLocationStack.children = @[_usernameNode]; }

// horizontal stack ASStackLayoutSpec *headerStackSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:40 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[nameLocationStack, _postTimeNode]];

// inset the horizontal stack return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0, 10, 0, 10) child:headerStackSpec]; }

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
  let nameLocationStack = ASStackLayoutSpec.vertical()
  nameLocationStack.style.flexShrink = 1.0
  nameLocationStack.style.flexGrow = 1.0

  if postLocationNode.attributedText != nil {
    nameLocationStack.children = [userNameNode, postLocationNode]
  } else {
    nameLocationStack.children = [userNameNode]
  }

  let headerStackSpec = ASStackLayoutSpec(direction: .horizontal,
                                          spacing: 40,
                                          justifyContent: .start,
                                          alignItems: .center,
                                          children: [nameLocationStack, postTimeNode])

  return ASInsetLayoutSpec(insets: UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10), child: headerStackSpec)
}
  

Rotate the example project from portrait to landscape to see how the spacer grows and shrinks.

Photo with Inset Text Overlay

To create this layout, we will use a:

  • ASInsetLayoutSpec to inset the text
  • ASOverlayLayoutSpec to overlay the inset text spec on top of the photo
Swift Objective-C
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
  _photoNode.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT*2, USER_IMAGE_HEIGHT*2);

// INIFINITY is used to make the inset unbounded UIEdgeInsets insets = UIEdgeInsetsMake(INFINITY, 12, 12, 12); ASInsetLayoutSpec *textInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:_titleNode];

return [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_photoNode overlay:textInsetSpec]; }

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
  let photoDimension: CGFloat = constrainedSize.max.width / 4.0
  photoNode.style.preferredSize = CGSize(width: photoDimension, height: photoDimension)

  // INFINITY is used to make the inset unbounded
  let insets = UIEdgeInsets(top: CGFloat.infinity, left: 12, bottom: 12, right: 12)
  let textInsetSpec = ASInsetLayoutSpec(insets: insets, child: titleNode)

  return ASOverlayLayoutSpec(child: photoNode, overlay: textInsetSpec)
}
  

Photo with Outset Icon Overlay

To create this layout, we will use a:

  • ASAbsoluteLayoutSpec to place the photo and icon which have been individually sized and positioned using their ASLayoutable properties
Swift Objective-C
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
  _iconNode.style.preferredSize = CGSizeMake(40, 40);
  _iconNode.style.layoutPosition = CGPointMake(150, 0);

_photoNode.style.preferredSize = CGSizeMake(150, 150); _photoNode.style.layoutPosition = CGPointMake(40 / 2.0, 40 / 2.0);

return [ASAbsoluteLayoutSpec absoluteLayoutSpecWithSizing:ASAbsoluteLayoutSpecSizingSizeToFit children:@[_photoNode, _iconNode]]; }

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
  iconNode.style.preferredSize = CGSize(width: 40, height: 40);
  iconNode.style.layoutPosition = CGPoint(x: 150, y: 0);

  photoNode.style.preferredSize = CGSize(width: 150, height: 150);
  photoNode.style.layoutPosition = CGPoint(x: 40 / 2.0, y: 40 / 2.0);

  let absoluteSpec = ASAbsoluteLayoutSpec(children: [photoNode, iconNode])

  // ASAbsoluteLayoutSpec's .sizing property recreates the behavior of Texture Layout API 1.0's "ASStaticLayoutSpec"
  absoluteSpec.sizing = .sizeToFit

  return absoluteSpec;
}
  

Simple Inset Text Cell

To recreate the layout of a single cell as is used in Pinterest's search view above, we will use a:

  • ASInsetLayoutSpec to inset the text
  • ASCenterLayoutSpec to center the text according to the specified properties
Swift Objective-C
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
    UIEdgeInsets insets = UIEdgeInsetsMake(0, 12, 4, 4);
    ASInsetLayoutSpec *inset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets
                                                                      child:_titleNode];
return [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringY
                                                  sizingOptions:ASCenterLayoutSpecSizingOptionMinimumX
                                                          child:inset];

}

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
    let insets = UIEdgeInsets(top: 0, left: 12, bottom: 4, right: 4)
    let inset = ASInsetLayoutSpec(insets: insets, child: _titleNode)
        
    return ASCenterLayoutSpec(centeringOptions: .Y, sizingOptions: .minimumX, child: inset)
}
  

Top and Bottom Separator Lines

To create the layout above, we will use a:

  • a ASInsetLayoutSpec to inset the text
  • a vertical ASStackLayoutSpec to stack the two separator lines on the top and bottom of the text

The diagram below shows the composition of the layoutables (layout specs + nodes).

The following code can also be found in the ASLayoutSpecPlayground example project.

Swift Objective-C
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
  _topSeparator.style.flexGrow = 1.0;
  _bottomSeparator.style.flexGrow = 1.0;

ASInsetLayoutSpec *insetContentSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(20, 20, 20, 20) child:_textNode];

return [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:0 justifyContent:ASStackLayoutJustifyContentCenter alignItems:ASStackLayoutAlignItemsStretch children:@[_topSeparator, insetContentSpec, _bottomSeparator]]; }

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
  topSeparator.style.flexGrow = 1.0
  bottomSeparator.style.flexGrow = 1.0
  textNode.style.alignSelf = .center

  let verticalStackSpec = ASStackLayoutSpec.vertical()
  verticalStackSpec.spacing = 20
  verticalStackSpec.justifyContent = .center
  verticalStackSpec.children = [topSeparator, textNode, bottomSeparator]

  return ASInsetLayoutSpec(insets:UIEdgeInsets(top: 60, left: 0, bottom: 60, right: 0), child: verticalStackSpec)
}