Still support -calculateLayoutThatFits: (and manual layout), for backward compatibility.

This commit is contained in:
Huy Nguyen
2015-06-28 20:22:40 +07:00
parent 95e787b226
commit dd29a890df
13 changed files with 121 additions and 68 deletions

View File

@@ -105,12 +105,12 @@ static const CGFloat kFontSize = 18.0f;
return self;
}
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize{
- (id<ASLayoutable>)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
static const CGFloat kHorizontalPadding = 15.0f;
static const CGFloat kVerticalPadding = 11.0f;
UIEdgeInsets insets = UIEdgeInsetsMake(kVerticalPadding, kHorizontalPadding, kVerticalPadding, kHorizontalPadding);
id<ASLayoutable> layout = [ASInsetLayoutNode newWithInsets:insets child:_textNode];
return [layout calculateLayoutThatFits:constrainedSize];
return [ASInsetLayoutNode newWithInsets:insets child:_textNode];
}
- (void)setText:(NSString *)text

View File

@@ -14,6 +14,7 @@
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASLayoutable.h>
/**
* The subclass header _ASDisplayNode+Subclasses_ defines the following methods that either must or can be overriden by
@@ -35,7 +36,7 @@
* variables.
*/
@interface ASDisplayNode (Subclassing)
@interface ASDisplayNode (Subclassing) <ASLayoutable>
/** @name View Configuration */
@@ -107,6 +108,55 @@
*/
- (void)layoutDidFinish;
/** @name Layout calculation */
/**
* @abstract Calculate a layout based on given size range.
*
* @param constrainedSize The minimum and maximum sizes the receiver should fit in.
*
* @return An ASLayout instance defining the layout of the receiver (and its children, if the box layout model is used).
*
* @discussion This method is called on a non-main thread. The default implementation calls either -layoutSpecThatFits:
* or -calculateSizeThatFits:, whichever method is available. Thus, subclasses rarely need to override this method,
* override -layoutSpecThatFits: or -calculateSizeThatFits: instead.
*
* @note This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead.
*/
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize;
/**
* @abstract Return the calculated size.
*
* @param constrainedSize The maximum size the receiver should fit in.
*
* @discussion Subclasses that override should expect this method to be called on a non-main thread. The returned size
* is wrapped in an ASLayout and cached by ASDisplayNode for quick access during -layout. Other expensive work that needs to
* be done before display can be performed here, and using ivars to cache any valuable intermediate results is
* encouraged.
*
* @note Subclasses that override are committed to manual layout. Therefore, -layout: must be overriden to layout all subnodes or subviews.
*
* @note This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead.
*/
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize;
/**
* @abstract Return a layout spec that describes the layout of the receiver and its children.
*
* @param constrainedSize The minimum and maximum sizes the receiver should fit in.
*
* @discussion Subclasses that override should expect this method to be called on a non-main thread. The returned layout spec
* is used to calculate an ASLayout and cached by ASDisplayNode for quick access during -layout. Other expensive work that needs to
* be done before display can be performed here, and using ivars to cache any valuable intermediate results is
* encouraged.
*
* @note This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead.
*/
- (id<ASLayoutable>)layoutSpecThatFits:(ASSizeRange)constrainedSize;
/**
* @abstract Invalidate previously measured and cached layout.
*

View File

@@ -11,8 +11,6 @@
#import <AsyncDisplayKit/_ASAsyncTransactionContainer.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASDealloc2MainObject.h>
#import <AsyncDisplayKit/ASLayoutable.h>
typedef UIView *(^ASDisplayNodeViewBlock)();
typedef CALayer *(^ASDisplayNodeLayerBlock)();
@@ -33,7 +31,7 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)();
*
*/
@interface ASDisplayNode : ASDealloc2MainObject <ASLayoutable>
@interface ASDisplayNode : ASDealloc2MainObject
/** @name Initializing a node object */
@@ -155,22 +153,6 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)();
*/
@property (nonatomic, readonly, assign) CGSize constrainedSizeForCalculatedLayout;
/**
* @abstract Calculate a layout based on given size range.
*
* @param constrainedSize The minimum and maximum sizes the receiver should fit in.
*
* @return An ASLayout instance defining the layout of the receiver and its children.
*
* @discussion Subclasses that override should expect this method to be called on a non-main thread. The returned layout
* is cached by ASDisplayNode for quick access during -layout, via -calculatedSize. Other expensive work that needs to
* be done before display can be performed here, and using ivars to cache any valuable intermediate results is
* encouraged.
*
* @note This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead.
*/
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize;
/** @name Managing the nodes hierarchy */

View File

@@ -76,6 +76,12 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(measure:)), @"Subclass %@ must not override measure method", NSStringFromClass(self));
ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(recursivelyClearContents)), @"Subclass %@ must not override recursivelyClearContents method", NSStringFromClass(self));
ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(recursivelyClearFetchedData)), @"Subclass %@ must not override recursivelyClearFetchedData method", NSStringFromClass(self));
// At most one of the three layout methods is overridden
ASDisplayNodeAssert((ASDisplayNodeSubclassOverridesSelector(self, @selector(calculateSizeThatFits:)) ? 1 : 0)
+ (ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutSpecThatFits:)) ? 1 : 0)
+ (ASDisplayNodeSubclassOverridesSelector(self, @selector(calculateLayoutThatFits:)) ? 1 : 0) <= 1,
@"Subclass %@ must override at most one of the three layout methods: calculateLayoutThatFits, layoutSpecThatFits or calculateSizeThatFits", NSStringFromClass(self));
}
+ (BOOL)layerBackedNodesEnabled
@@ -122,6 +128,9 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
if (ASDisplayNodeSubclassOverridesSelector([self class], @selector(touchesEnded:withEvent:))) {
overrides |= ASDisplayNodeMethodOverrideTouchesEnded;
}
if (ASDisplayNodeSubclassOverridesSelector([self class], @selector(calculateSizeThatFits:))) {
overrides |= ASDisplayNodeMethodOverrideCalculateSizeThatFits;
}
_methodOverrides = overrides;
_flexBasis = ASRelativeDimensionUnconstrained;
@@ -1271,7 +1280,25 @@ static NSInteger incrementIfFound(NSInteger i) {
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
ASDisplayNodeAssertThreadAffinity(self);
return [ASLayout newWithLayoutableObject:self size:constrainedSize.min];
if (_methodOverrides & ASDisplayNodeMethodOverrideCalculateSizeThatFits) {
CGSize size = [self calculateSizeThatFits:constrainedSize.max];
return [ASLayout newWithLayoutableObject:self size:ASSizeRangeClamp(constrainedSize, size)];
} else {
id<ASLayoutable> layoutSpec = [self layoutSpecThatFits:constrainedSize];
return [layoutSpec calculateLayoutThatFits:constrainedSize];
}
}
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
ASDisplayNodeAssertThreadAffinity(self);
return CGSizeZero;
}
- (id<ASLayoutable>)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
ASDisplayNodeAssertThreadAffinity(self);
return nil;
}
- (ASLayout *)calculatedLayout

View File

@@ -145,12 +145,11 @@
[self.view addSubview:_textKitComponents.textView];
}
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
ASTextKitComponents *displayedComponents = [self isDisplayingPlaceholder] ? _placeholderTextKitComponents : _textKitComponents;
CGSize textSize = [displayedComponents sizeForConstrainedWidth:constrainedSize.max.width];
CGSize finalSize = CGSizeMake(constrainedSize.max.width, fminf(textSize.height, constrainedSize.max.height));
return [ASLayout newWithLayoutableObject:self size:finalSize];
CGSize textSize = [displayedComponents sizeForConstrainedWidth:constrainedSize.width];
return CGSizeMake(constrainedSize.width, fminf(textSize.height, constrainedSize.height));
}
- (void)layout

View File

@@ -108,13 +108,13 @@
return nil;
}
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
ASDN::MutexLocker l(_imageLock);
CGSize size = CGSizeZero;
if (_image)
size = _image.size;
return [ASLayout newWithLayoutableObject:self size:ASSizeRangeClamp(constrainedSize, size)];
return _image.size;
else
return CGSizeZero;
}
- (void)setImage:(UIImage *)image

View File

@@ -186,10 +186,10 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
#pragma mark - ASDisplayNode
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
ASDisplayNodeAssert(constrainedSize.max.width >= 0, @"Constrained width for text (%f) is too narrow", constrainedSize.max.width);
ASDisplayNodeAssert(constrainedSize.max.height >= 0, @"Constrained height for text (%f) is too short", constrainedSize.max.height);
ASDisplayNodeAssert(constrainedSize.width >= 0, @"Constrained width for text (%f) is too narrow", constrainedSize.width);
ASDisplayNodeAssert(constrainedSize.height >= 0, @"Constrained height for text (%f) is too short", constrainedSize.height);
// The supplied constrainedSize should include room for shadowPadding.
// Inset the constrainedSize by the shadow padding to get the size available for text.
UIEdgeInsets shadowPadding = [[self _shadower] shadowPadding];
@@ -197,7 +197,7 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
UIEdgeInsets shadowPaddingOutset = ASDNEdgeInsetsInvert(shadowPadding);
// Inset the padded constrainedSize to get the remaining size available for text
CGRect constrainedRect = CGRect{CGPointZero, constrainedSize.max};
CGRect constrainedRect = CGRect{CGPointZero, constrainedSize};
CGSize constrainedSizeForText = UIEdgeInsetsInsetRect(constrainedRect, shadowPaddingOutset).size;
ASDisplayNodeAssert(constrainedSizeForText.width >= 0, @"Constrained width for text (%f) after subtracting shadow padding (%@) is too narrow", constrainedSizeForText.width, NSStringFromUIEdgeInsets(shadowPadding));
ASDisplayNodeAssert(constrainedSizeForText.height >= 0, @"Constrained height for text (%f) after subtracting shadow padding (%@) is too short", constrainedSizeForText.height, NSStringFromUIEdgeInsets(shadowPadding));
@@ -212,9 +212,8 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
ASDisplayNodeAssert(renderSizePlusShadowPadding.width >= 0, @"Calculated width for text with shadow padding (%f) is too narrow", constrainedSizeForText.width);
ASDisplayNodeAssert(renderSizePlusShadowPadding.height >= 0, @"Calculated height for text with shadow padding (%f) is too short", constrainedSizeForText.height);
CGSize finalSize = CGSizeMake(MIN(ceilPixelValue(renderSizePlusShadowPadding.width), constrainedSize.max.width),
MIN(ceilPixelValue(renderSizePlusShadowPadding.height), constrainedSize.max.height));
return [ASLayout newWithLayoutableObject:self size:finalSize];
return CGSizeMake(MIN(ceilPixelValue(renderSizePlusShadowPadding.width), constrainedSize.width),
MIN(ceilPixelValue(renderSizePlusShadowPadding.height), constrainedSize.height));
}
- (void)displayDidFinish

View File

@@ -24,10 +24,11 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)());
typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
ASDisplayNodeMethodOverrideNone = 0,
ASDisplayNodeMethodOverrideTouchesBegan = 1 << 0,
ASDisplayNodeMethodOverrideTouchesCancelled = 1 << 1,
ASDisplayNodeMethodOverrideTouchesEnded = 1 << 2,
ASDisplayNodeMethodOverrideTouchesMoved = 1 << 3
ASDisplayNodeMethodOverrideTouchesBegan = 1 << 0,
ASDisplayNodeMethodOverrideTouchesCancelled = 1 << 1,
ASDisplayNodeMethodOverrideTouchesEnded = 1 << 2,
ASDisplayNodeMethodOverrideTouchesMoved = 1 << 3,
ASDisplayNodeMethodOverrideCalculateSizeThatFits = 1 << 4
};
@class _ASPendingState;