Merge pull request #594 from nguyenhuy/relayout_same_constrained_size

Support internal relayout
This commit is contained in:
appleguy 2015-08-04 12:27:30 -07:00
commit f97af9cb26
7 changed files with 73 additions and 6 deletions

View File

@ -505,8 +505,22 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)();
*/
@interface ASDisplayNode (UIViewBridge)
- (void)setNeedsDisplay; // Marks the view as needing display. Convenience for use whether view is created or not, or from a background thread.
- (void)setNeedsLayout; // Marks the view as needing layout. Convenience for use whether view is created or not, or from a background thread.
/**
* Marks the view as needing display. Convenience for use whether the view / layer is loaded or not. Safe to call from a background thread.
*/
- (void)setNeedsDisplay;
/**
* Marks the node as needing layout. Convenience for use whether the view / layer is loaded or not. Safe to call from a background thread.
*
* If this node was measured, calling this method triggers an internal relayout: the calculated layout is invalidated,
* and the supernode is notified or (if this node is the root one) a full measurement pass is executed using the old constrained size.
*
* Note: If the relayout causes a change in size of the root node that is attached to a container view
* (table or collection view, for example), the container view must be notified to relayout.
* For ASTableView and ASCollectionView, an empty batch editing transaction must be triggered to animate to new row / item sizes.
*/
- (void)setNeedsLayout;
@property (atomic, retain) id contents; // default=nil
@property (atomic, assign) BOOL clipsToBounds; // default==NO

View File

@ -560,6 +560,30 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
[[self asyncLayer] displayImmediately];
}
- (void)__setNeedsLayout
{
ASDisplayNodeAssertThreadAffinity(self);
ASDN::MutexLocker l(_propertyLock);
if (!_flags.isMeasured) {
return;
}
ASSizeRange oldConstrainedSize = _constrainedSize;
[self invalidateCalculatedLayout];
if (_supernode) {
// Cause supernode's layout to be invalidated
[_supernode setNeedsLayout];
} else {
// This is the root node. Trigger a full measurement pass on *current* thread. Old constrained size is re-used.
[self measureWithSizeRange:oldConstrainedSize];
CGRect bounds = self.bounds;
bounds.size = CGSizeMake(_layout.size.width, _layout.size.height);
self.bounds = bounds;
}
}
// These private methods ensure that subclasses are not required to call super in order for _renderingSubnodes to be properly managed.
- (void)__layout

View File

@ -174,6 +174,7 @@
- (void)setNeedsLayout
{
_bridge_prologue;
[self __setNeedsLayout];
_messageToViewOrLayer(setNeedsLayout);
}

View File

@ -121,6 +121,7 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
// Core implementation of -measureWithSizeRange:. Must be called with _propertyLock held.
- (ASLayout *)__measureWithSizeRange:(ASSizeRange)constrainedSize;
- (void)__setNeedsLayout;
- (void)__layout;
- (void)__setSupernode:(ASDisplayNode *)supernode;

View File

@ -19,4 +19,6 @@
- (instancetype)initWithKittenOfSize:(CGSize)size;
- (void)toggleImageEnlargement;
@end

View File

@ -29,6 +29,8 @@ static const CGFloat kInnerPadding = 10.0f;
ASNetworkImageNode *_imageNode;
ASTextNode *_textNode;
ASDisplayNode *_divider;
BOOL _isImageEnlarged;
BOOL _swappedTextAndImage;
}
@end
@ -84,6 +86,7 @@ static const CGFloat kInnerPadding = 10.0f;
(NSInteger)roundl(_kittenSize.width),
(NSInteger)roundl(_kittenSize.height)]];
// _imageNode.contentMode = UIViewContentModeCenter;
[_imageNode addTarget:self action:@selector(toggleNodesSwap) forControlEvents:ASControlNodeEventTouchUpInside];
[self addSubnode:_imageNode];
// lorem ipsum text, plus some nice styling
@ -132,7 +135,7 @@ static const CGFloat kInnerPadding = 10.0f;
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
ASRatioLayoutSpec *imagePlaceholder = [ASRatioLayoutSpec newWithRatio:1.0 child:_imageNode];
imagePlaceholder.flexBasis = ASRelativeDimensionMakeWithPoints(kImageSize);
imagePlaceholder.flexBasis = ASRelativeDimensionMakeWithPoints(kImageSize * (!_isImageEnlarged ? 1 : 2));
_textNode.flexShrink = YES;
@ -145,7 +148,7 @@ static const CGFloat kInnerPadding = 10.0f;
.direction = ASStackLayoutDirectionHorizontal,
.spacing = kInnerPadding
}
children:@[imagePlaceholder, _textNode]]];
children:!_swappedTextAndImage ? @[imagePlaceholder, _textNode] : @[_textNode, imagePlaceholder]]];
}
// With box model, you don't need to override this method, unless you want to add custom logic.
@ -181,4 +184,16 @@ static const CGFloat kInnerPadding = 10.0f;
}
#endif
- (void)toggleImageEnlargement
{
_isImageEnlarged = !_isImageEnlarged;
[self setNeedsLayout];
}
- (void)toggleNodesSwap
{
_swappedTextAndImage = !_swappedTextAndImage;
[self setNeedsLayout];
}
@end

View File

@ -102,6 +102,16 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell
#pragma mark -
#pragma mark ASTableView.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[_tableView deselectRowAtIndexPath:indexPath animated:YES];
[_tableView beginUpdates];
// Assume only kitten nodes are selectable (see -tableView:shouldHighlightRowAtIndexPath:).
KittenNode *node = (KittenNode *)[_tableView nodeForRowAtIndexPath:indexPath];
[node toggleImageEnlargement];
[_tableView endUpdates];
}
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
{
// special-case the first row
@ -123,8 +133,8 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
// disable row selection
return NO;
// Enable selection for kitten nodes
return indexPath.section != 0 || indexPath.row != 0;
}
- (void)tableViewLockDataSource:(ASTableView *)tableView