diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index f748693040..0311a3028d 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -185,6 +185,14 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)(); */ @property (nonatomic, readonly, assign) ASSizeRange constrainedSizeForCalculatedLayout; +/** + * @abstract Used by some implementations of measureWithSizeRange: to provide an intrisic content size + * to a node when one cannot be computed from its subnodes + * + * @return The preferred frame size of this node + */ +@property (atomic, assign, readwrite) CGSize preferredFrameSize; + /** @name Managing the nodes hierarchy */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index d9fe7520bd..b5cdf6be59 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -47,6 +47,7 @@ @synthesize flexShrink = _flexShrink; @synthesize flexBasis = _flexBasis; @synthesize alignSelf = _alignSelf; +@synthesize preferredFrameSize = _preferredFrameSize; BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) { @@ -135,6 +136,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)()) _methodOverrides = overrides; _flexBasis = ASRelativeDimensionUnconstrained; + _preferredFrameSize = CGSizeZero; } - (id)init @@ -1330,7 +1332,7 @@ static NSInteger incrementIfFound(NSInteger i) { - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize { ASDisplayNodeAssertThreadAffinity(self); - return CGSizeZero; + return _preferredFrameSize; } - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize @@ -1357,6 +1359,17 @@ static NSInteger incrementIfFound(NSInteger i) { return _constrainedSize; } +- (void)setPreferredFrameSize:(CGSize)preferredFrameSize +{ + ASDN::MutexLocker l(_propertyLock); + _preferredFrameSize = preferredFrameSize; +} + +- (CGSize)preferredFrameSize +{ + ASDN::MutexLocker l(_propertyLock); + return _preferredFrameSize; +} - (UIImage *)placeholderImage { return nil; diff --git a/AsyncDisplayKit/ASImageNode.mm b/AsyncDisplayKit/ASImageNode.mm index d7cdebbd94..2db88e5fef 100644 --- a/AsyncDisplayKit/ASImageNode.mm +++ b/AsyncDisplayKit/ASImageNode.mm @@ -111,7 +111,9 @@ - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize { ASDN::MutexLocker l(_imageLock); - if (_image) + if (CGSizeEqualToSize(self.preferredFrameSize, CGSizeZero) == NO) + return CGSizeMake(MIN(constrainedSize.width, self.preferredFrameSize.width), MIN(constrainedSize.height, self.preferredFrameSize.height)); + else if (_image) return _image.size; else return CGSizeZero; diff --git a/examples/Kittens/Sample/KittenNode.mm b/examples/Kittens/Sample/KittenNode.mm index de8d0384e4..a852bcb801 100644 --- a/examples/Kittens/Sample/KittenNode.mm +++ b/examples/Kittens/Sample/KittenNode.mm @@ -134,9 +134,7 @@ static const CGFloat kInnerPadding = 10.0f; #if UseAutomaticLayout - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - ASRatioLayoutSpec *imagePlaceholder = [ASRatioLayoutSpec newWithRatio:1.0 child:_imageNode]; - imagePlaceholder.flexBasis = ASRelativeDimensionMakeWithPoints(kImageSize * (!_isImageEnlarged ? 1 : 2)); - + _imageNode.preferredFrameSize = _isImageEnlarged ? CGSizeMake(2.0 * kImageSize, 2.0 * kImageSize) : CGSizeMake(kImageSize, kImageSize); _textNode.flexShrink = YES; return @@ -148,7 +146,7 @@ static const CGFloat kInnerPadding = 10.0f; .direction = ASStackLayoutDirectionHorizontal, .spacing = kInnerPadding } - children:!_swappedTextAndImage ? @[imagePlaceholder, _textNode] : @[_textNode, imagePlaceholder]]]; + children:!_swappedTextAndImage ? @[_imageNode, _textNode] : @[_textNode, _imageNode]]]; } // With box model, you don't need to override this method, unless you want to add custom logic.