[Layout] Layout API based on content area (#2110)

* Initial commit for adding a size constraint to ASLayoutable's

* Some more commits

* Fix sample projects in extra/

* Remove preferredFrameSize test of ASEditableTextNode

* Remove preferredFrameSize from examples_extra

* Add deprecation warning to -[ASDisplayNode preferredFrameSize]

* Add deprecation warning to -[ASDisplayNode measureWithSizeRange:]

* Commit

* Commit

* Remove ASRelativeSizeRange

* Make ASRelativeSize private

* Adjust examples

* Improve setting of -[ASLayoutable size] with points or fractions

* Add ASWrapperLayoutSpec

* Improve creation of ASRelativeDimension

* Add `preferredFrameSize` back and add deprecated logging

* Add `layoutSpecBlock` setter and getter and add locking for it

* Add better documentation and fix macros to create ASRelativeDimension

* Create new ASSizeRangeMake with just a CGSize as parameter

* Update Kitten and Social App Layout example

* Add layoutThatFits: and deprecate measure:

* Rename ASRelativeDimension to ASDimension

* Fix examples for ASDimension renaming

* Remove fancy height and width setter

* Fix ASDimension helper

* Rename -[ASLayout layoutableObject] to -[ASLayout layoutable]

* Update layout related methods and more clearer documentation around how to use it

* Deprecate old ASLayout class constructors

* Don't unnecessary recalculate layout if constrained or parent size did not change

* Use shared pointer for ASDisplayNodeLayout

* Fix rebase conflicts

* Add documentation and move implementation in mm file of ASDisplayNodeLayout

* Fix test errors

* Rename ASSize to ASLayoutableSize

* Address comments

* Rename setSizeFromCGSize to setSizeWithCGSize

* Improve inline functions in ASDimension

* Fix rebase conflicts
This commit is contained in:
Michael Schneider
2016-09-07 17:44:48 +02:00
committed by Adlai Holler
parent 2bfeb6de92
commit 8897614f0e
109 changed files with 2089 additions and 1304 deletions

View File

@@ -45,8 +45,10 @@
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
self.node.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(constrainedSize.max);
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[self.node]];
// 100% of container
_node.width = ASDimensionMakeWithFraction(1.0);
_node.height = ASDimensionMakeWithFraction(1.0);
return [ASWrapperLayoutSpec wrapperWithLayoutable:_node];
}
#pragma mark - <ASCollectionDataSource, ASCollectionDelegate>

View File

@@ -37,9 +37,7 @@ static UIColor *OverViewASPagerNodeRandomColor() {
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:constrainedSize.max];
return [ASLayout layoutWithLayoutable:self size:constrainedSize.max];
}
@end
@@ -69,8 +67,10 @@ static UIColor *OverViewASPagerNodeRandomColor() {
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
_node.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(constrainedSize.max);
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[_node]];
// 100% of container
_node.width = ASDimensionMakeWithFraction(1.0);
_node.height = ASDimensionMakeWithFraction(1.0);
return [ASWrapperLayoutSpec wrapperWithLayoutable:_node];
}
- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode

View File

@@ -42,8 +42,10 @@
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
_node.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(constrainedSize.max);
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[_node]];
// 100% of container
_node.width = ASDimensionMakeWithFraction(1.0);
_node.height = ASDimensionMakeWithFraction(1.0);
return [ASWrapperLayoutSpec wrapperWithLayoutable:_node];
}

View File

@@ -82,6 +82,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
BOOL hasDescription = self.descriptionNode.attributedText.length > 0;
ASStackLayoutSpec *verticalStackLayoutSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
verticalStackLayoutSpec.alignItems = ASStackLayoutAlignItemsStart;
verticalStackLayoutSpec.spacing = 5.0;
verticalStackLayoutSpec.children = hasDescription ? @[self.titleNode, self.descriptionNode] : @[self.titleNode];
@@ -203,8 +204,11 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
#pragma mark ASImageNode
ASImageNode *imageNode = [ASImageNode new];
imageNode.image = [UIImage imageNamed:@"image"];
imageNode.preferredFrameSize = CGSizeMake(imageNode.image.size.width / 7, imageNode.image.size.height / 7);
imageNode.image = [UIImage imageNamed:@"image.jpg"];
CGSize imageNetworkImageNodeSize = (CGSize){imageNode.image.size.width / 7, imageNode.image.size.height / 7};
[imageNode setSizeWithCGSize:imageNetworkImageNodeSize];
parentNode = [self centeringParentNodeWithChild:imageNode];
parentNode.entryTitle = @"ASImageNode";
@@ -214,7 +218,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
#pragma mark ASNetworkImageNode
ASNetworkImageNode *networkImageNode = [ASNetworkImageNode new];
networkImageNode.URL = [NSURL URLWithString:@"http://i.imgur.com/FjOR9kX.jpg"];
networkImageNode.preferredFrameSize = CGSizeMake(imageNode.image.size.width / 7, imageNode.image.size.height / 7);
[networkImageNode setSizeWithCGSize:imageNetworkImageNodeSize];
parentNode = [self centeringParentNodeWithChild:networkImageNode];
parentNode.entryTitle = @"ASNetworkImageNode";
@@ -223,7 +227,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
#pragma mark ASMapNode
ASMapNode *mapNode = [ASMapNode new];
mapNode.preferredFrameSize = CGSizeMake(300.0, 300.0);
[mapNode setSizeWithCGSize:(CGSize){300.0, 300.0}];
// San Francisco
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(37.7749, -122.4194);
@@ -236,7 +240,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
#pragma mark ASVideoNode
ASVideoNode *videoNode = [ASVideoNode new];
videoNode.preferredFrameSize = CGSizeMake(300.0, 400.0);
[videoNode setSizeWithCGSize:(CGSize){300.0, 400.0}];
AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"http://www.w3schools.com/html/mov_bbb.mp4"]];
videoNode.asset = asset;
@@ -250,7 +254,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
UIImage *scrollNodeImage = [UIImage imageNamed:@"image"];
ASScrollNode *scrollNode = [ASScrollNode new];
scrollNode.preferredFrameSize = CGSizeMake(300.0, 400.0);
[scrollNode setSizeWithCGSize:(CGSize){300.0, 400.0}];
UIScrollView *scrollNodeView = scrollNode.view;
[scrollNodeView addSubview:[[UIImageView alloc] initWithImage:scrollNodeImage]];
@@ -391,6 +395,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
parentNode.entryDescription = @"Is based on a simplified version of CSS flexbox. It allows you to stack components vertically or horizontally and specify how they should be flexed and aligned to fit in the available space.";
parentNode.sizeThatFitsBlock = ^ASLayoutSpec *(ASSizeRange constrainedSize) {
ASStackLayoutSpec *verticalStackLayoutSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
verticalStackLayoutSpec.alignItems = ASStackLayoutAlignItemsStart;
verticalStackLayoutSpec.children = @[childNode1, childNode2, childNode3];
return verticalStackLayoutSpec;
};
@@ -401,17 +406,17 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
#pragma mark Horizontal ASStackLayoutSpec
childNode1 = [ASDisplayNode new];
childNode1.preferredFrameSize = CGSizeMake(10.0, 20);
[childNode1 setSizeWithCGSize:(CGSize){10.0, 20.0}];
childNode1.flexGrow = YES;
childNode1.backgroundColor = [UIColor greenColor];
childNode2 = [ASDisplayNode new];
childNode2.preferredFrameSize = CGSizeMake(10.0, 20.0);
[childNode2 setSizeWithCGSize:(CGSize){10.0, 20.0}];
childNode2.alignSelf = ASStackLayoutAlignSelfStretch;
childNode2.backgroundColor = [UIColor blueColor];
childNode3 = [ASDisplayNode new];
childNode3.preferredFrameSize = CGSizeMake(10.0, 20.0);
[childNode3 setSizeWithCGSize:(CGSize){10.0, 20.0}];
childNode3.backgroundColor = [UIColor yellowColor];
parentNode = [self parentNodeWithChild:childNode];
@@ -420,20 +425,17 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
parentNode.sizeThatFitsBlock = ^ASLayoutSpec *(ASSizeRange constrainedSize) {
// Create stack alyout spec to layout children
ASStackLayoutSpec *verticalStackLayoutSpec = [ASStackLayoutSpec horizontalStackLayoutSpec];
verticalStackLayoutSpec.children = @[childNode1, childNode2, childNode3];
verticalStackLayoutSpec.spacing = 5.0; // Spacing between children
ASStackLayoutSpec *horizontalStackSpec = [ASStackLayoutSpec horizontalStackLayoutSpec];
horizontalStackSpec.alignItems = ASStackLayoutAlignItemsStart;
horizontalStackSpec.children = @[childNode1, childNode2, childNode3];
horizontalStackSpec.spacing = 5.0; // Spacing between children
// Layout the stack layout with 100% width and 100% height of the parent node
ASRelativeSizeRange sizeRange = ASRelativeSizeRangeMakeWithExactRelativeDimensions(ASRelativeDimensionMakeWithFraction(1),
ASRelativeDimensionMakeWithFraction(1));
verticalStackLayoutSpec.sizeRange = sizeRange;
// Wrap the static stack layout in a static spec so it will grow to the whole parent node size
ASStaticLayoutSpec *staticLayoutSpec = [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[verticalStackLayoutSpec]];
horizontalStackSpec.height = ASDimensionMakeWithFraction(1.0);
horizontalStackSpec.width = ASDimensionMakeWithFraction(1.0);
// Add a bit of inset
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0.0, 5.0, 0.0, 5.0) child:staticLayoutSpec];
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0.0, 5.0, 0.0, 5.0) child:horizontalStackSpec];
};
[parentNode addSubnode:childNode1];
[parentNode addSubnode:childNode2];
@@ -465,7 +467,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
- (OverviewDisplayNodeWithSizeBlock *)parentNodeWithChild:(ASDisplayNode *)child
{
OverviewDisplayNodeWithSizeBlock *parentNode = [OverviewDisplayNodeWithSizeBlock new];
parentNode.preferredFrameSize = CGSizeMake(100, 100);
[parentNode setSizeWithCGSize:(CGSize){100, 100}];
parentNode.backgroundColor = [UIColor redColor];
return parentNode;
}
@@ -489,7 +491,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr
- (ASDisplayNode *)childNode
{
ASDisplayNode *childNode = [ASDisplayNode new];
childNode.preferredFrameSize = CGSizeMake(50, 50);
[childNode setSizeWithCGSize:(CGSize){50, 50}];
childNode.backgroundColor = [UIColor blueColor];
return childNode;
}

View File

@@ -51,12 +51,11 @@
// Center node frame
CGRect bounds = self.view.bounds;
CGSize nodeSize = self.node.preferredFrameSize;
if (CGSizeEqualToSize(nodeSize, CGSizeZero)) {
nodeSize = self.view.bounds.size;
}
self.node.frame = CGRectMake(CGRectGetMidX(bounds) - (nodeSize.width / 2.0), CGRectGetMidY(bounds) - (nodeSize.height / 2.0), nodeSize.width, nodeSize.height);
[self.node measure:self.node.bounds.size];
CGSize nodeSize = [self.node layoutThatFits:ASSizeRangeMake(CGSizeZero, bounds.size)].size;
self.node.frame = CGRectMake(CGRectGetMidX(bounds) - (nodeSize.width / 2.0),
CGRectGetMidY(bounds) - (nodeSize.height / 2.0),
nodeSize.width,
nodeSize.height);
}
@end