Perform animation transition on measureWithSizeRange instead of separate method

This commit is contained in:
Levi McCallum
2016-02-09 11:05:06 -08:00
parent 8238da8d00
commit d8d76635ff
7 changed files with 80 additions and 56 deletions

View File

@@ -15,6 +15,10 @@
*/
- (BOOL)isAnimated;
- (ASLayout *)layout;
- (ASSizeRange)constrainedSize;
/**
@abstract The frame for the given node before the transition began.
@discussion Returns CGRectNull if the node was not in the hierarchy before the transition.

View File

@@ -6,6 +6,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "ASContextTransitioning.h"
@interface ASDisplayNode (Beta)
+ (BOOL)usesImplicitHierarchyManagement;
@@ -37,4 +39,32 @@
*/
@property (nonatomic, strong) ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext;
/** @name Layout Transitioning */
/**
@discussion A place to perform your animation. New nodes have been inserted here. You can also use this time to re-order the hierarchy.
*/
- (void)animateLayoutTransition:(id<ASContextTransitioning>)context;
/**
@discussion A place to clean up your nodes after the transition
*/
- (void)didCompleteLayoutTransition:(id<ASContextTransitioning>)context;
/**
@abstract Invalidates the current layout and begins a relayout of the node to the new layout returned in `calculateLayoutThatFits:`.
@discussion Animation is optional, but will still proceed through the `transitionLayout` methods with `isAnimated == NO`.
*/
//- (void)transitionLayoutWithAnimation:(BOOL)animated;
/**
@abstract Invalidates the current layout and begins a relayout of the node to the new layout returned in `calculateLayoutThatFits:`.
@discussion Animation is optional, but will still proceed through the `transitionLayout` methods with `isAnimated == NO`.
*/
//- (void)transitionLayoutThatFits:(ASSizeRange)constrainedSize animated:(BOOL)animated;
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize animated:(BOOL)animated;
@end

View File

@@ -12,7 +12,6 @@
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASContextTransitioning.h>
@class ASLayoutSpec;
@@ -156,19 +155,6 @@ NS_ASSUME_NONNULL_BEGIN
- (void)invalidateCalculatedLayout;
/** @name Layout Transitioning */
/**
@discussion A place to perform your animation. New nodes have been inserted here. You can also use this time to re-order the hierarchy.
*/
- (void)animateLayoutTransition:(id<ASContextTransitioning>)context;
/**
@discussion A place to clean up your nodes after the transition
*/
- (void)didCompleteLayoutTransition:(id<ASContextTransitioning>)context;
/** @name Drawing */

View File

@@ -571,18 +571,6 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface ASDisplayNode (Transitioning)
/**
@abstract Invalidates the current layout and begins a relayout of the node to the new layout returned in `calculateLayoutThatFits:`.
@discussion Animation is optional, but will still proceed through the `transitionLayout` methods with `isAnimated == NO`.
*/
- (void)transitionLayoutWithAnimation:(BOOL)animated;
@end
/**
* Convenience methods for debugging.
*/

View File

@@ -644,6 +644,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
}
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{
return [self measureWithSizeRange:constrainedSize animated:NO];
}
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize animated:(BOOL)animated
{
ASDisplayNodeAssertThreadAffinity(self);
ASDN::MutexLocker l(_propertyLock);
@@ -651,11 +656,13 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
if (![self __shouldSize])
return nil;
ASLayout *newLayout;
// only calculate the size if
// - we haven't already
// - the constrained size range is different
if (!_flags.isMeasured || !ASSizeRangeEqualToSizeRange(constrainedSize, _constrainedSize)) {
ASLayout *newLayout = [self calculateLayoutThatFits:constrainedSize];
newLayout = [self calculateLayoutThatFits:constrainedSize];
if ([[self class] usesImplicitHierarchyManagement]) {
if (_layout) {
@@ -674,22 +681,37 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
_deletedSubnodes = nil;
}
if (!_deferImmediateHierarchyManagement) {
if (animated) {
[self __transitionToLayout:newLayout constrainedSize:constrainedSize animated:animated];
} else {
[self __implicitlyInsertSubnodes];
[self __implicitlyRemoveSubnodes];
[self __updateLayout:newLayout constrainedSize:constrainedSize];
}
} else {
// 1.9.x code path
[self __updateLayout:newLayout constrainedSize:constrainedSize];
}
}
return newLayout;
}
_layout = newLayout;
- (void)__updateLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize
{
ASDisplayNodeAssertTrue(layout.layoutableObject == self);
ASDisplayNodeAssertTrue(layout.size.width >= 0.0);
ASDisplayNodeAssertTrue(layout.size.height >= 0.0);
_layout = layout;
_constrainedSize = constrainedSize;
_flags.isMeasured = YES;
[self calculatedLayoutDidChange];
[self __primePlaceholder];
}
ASDisplayNodeAssertTrue(_layout.layoutableObject == self);
ASDisplayNodeAssertTrue(_layout.size.width >= 0.0);
ASDisplayNodeAssertTrue(_layout.size.height >= 0.0);
- (void)__primePlaceholder
{
// we generate placeholders at measureWithSizeRange: time so that a node is guaranteed
// to have a placeholder ready to go. Also, if a node has no size it should not have a placeholder
if (self.placeholderEnabled && [self _displaysAsynchronously] &&
@@ -702,8 +724,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
[self _setupPlaceholderLayerContents];
}
}
return _layout;
}
/**
@@ -1033,23 +1053,12 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
#pragma mark - Layout Transition
- (void)transitionLayoutWithAnimation:(BOOL)animated
- (void)__transitionToLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize animated:(BOOL)animated
{
[self transitionLayoutThatFits:_constrainedSize animated:animated];
}
- (void)transitionLayoutThatFits:(ASSizeRange)constrainedSize animated:(BOOL)animated
{
[self invalidateCalculatedLayout];
_deferImmediateHierarchyManagement = YES;
[self measureWithSizeRange:constrainedSize]; // Generate a new layout
_deferImmediateHierarchyManagement = NO;
[self __transitionLayoutWithAnimation:animated];
}
- (void)__transitionLayoutWithAnimation:(BOOL)animated
{
_transitionContext = [[_ASTransitionContext alloc] initWithAnimation:animated delegate:self];
_transitionContext = [[_ASTransitionContext alloc] initWithLayout:layout
constrainedSize:constrainedSize
animated:animated
delegate:self];
[self __implicitlyInsertSubnodes];
[self animateLayoutTransition:_transitionContext];
}
@@ -1063,6 +1072,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
- (void)didCompleteTransitionLayout:(id<ASContextTransitioning>)context
{
[self __implicitlyRemoveSubnodes];
[self __updateLayout:context.layout constrainedSize:context.constrainedSize];
}
#pragma mark - Implicit node hierarchy managagment

View File

@@ -25,6 +25,10 @@
@property (assign, readonly, nonatomic, getter=isAnimated) BOOL animated;
- (instancetype)initWithAnimation:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate;
@property (strong, readonly) ASLayout *layout;
@property (assign, readonly) ASSizeRange constrainedSize;
- (instancetype)initWithLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize animated:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate;
@end

View File

@@ -16,10 +16,12 @@
@implementation _ASTransitionContext
- (instancetype)initWithAnimation:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate
- (instancetype)initWithLayout:(ASLayout *)layout constrainedSize:(ASSizeRange)constrainedSize animated:(BOOL)animated delegate:(id<_ASTransitionContextDelegate>)delegate
{
self = [super init];
if (self) {
_layout = layout;
_constrainedSize = constrainedSize;
_animated = animated;
_delegate = delegate;
}