From ddc23af8e7a8f5c2c6e9b6a8f9dde204ddb25917 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Mon, 12 Dec 2016 19:46:01 -0800 Subject: [PATCH] [Layout Transition] Reset the alpha value for inserted and removed subnode to initial value (#2729) * Reset the alpha value for removed subnodes in layout transition to 1 after removal * Some improvements * Restore alpha value of inserted and removed subnodes to original alpha value in animated layout transition --- AsyncDisplayKit/ASDisplayNode.mm | 32 +++++++++++++++++++------- AsyncDisplayKit/_ASTransitionContext.h | 6 +++++ AsyncDisplayKit/_ASTransitionContext.m | 18 +++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index f59c050aa4..859e7caabf 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1057,9 +1057,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) // Kick off animating the layout transition [self animateLayoutTransition:_pendingLayoutTransitionContext]; - - // Mark transaction as finished - [self _finishOrCancelTransition]; }); }; @@ -1184,6 +1181,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) NSMutableArray *insertedSubnodes = [[context insertedSubnodes] mutableCopy]; NSMutableArray *movedSubnodes = [NSMutableArray array]; + NSMutableArray<_ASAnimatedTransitionContext *> *insertedSubnodeContexts = [NSMutableArray array]; + NSMutableArray<_ASAnimatedTransitionContext *> *removedSubnodeContexts = [NSMutableArray array]; + for (ASDisplayNode *subnode in [context subnodesForKey:ASTransitionContextToLayoutKey]) { if ([insertedSubnodes containsObject:subnode] == NO) { // This is an existing subnode, check if it is resized, moved or both @@ -1207,6 +1207,15 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) } } + // Create contexts for inserted and removed subnodes + for (ASDisplayNode *insertedSubnode in insertedSubnodes) { + [insertedSubnodeContexts addObject:[_ASAnimatedTransitionContext contextForNode:insertedSubnode alpha:insertedSubnode.alpha]]; + } + for (ASDisplayNode *removedSubnode in removedSubnodes) { + [removedSubnodeContexts addObject:[_ASAnimatedTransitionContext contextForNode:removedSubnode alpha:removedSubnode.alpha]]; + } + + // Fade out inserted subnodes for (ASDisplayNode *insertedSubnode in insertedSubnodes) { insertedSubnode.frame = [context finalFrameForNode:insertedSubnode]; insertedSubnode.alpha = 0; @@ -1222,8 +1231,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) } // Fade inserted subnodes in - for (ASDisplayNode *insertedSubnode in insertedSubnodes) { - insertedSubnode.alpha = 1; + for (_ASAnimatedTransitionContext *insertedSubnodeContext in insertedSubnodeContexts) { + insertedSubnodeContext.node.alpha = insertedSubnodeContext.alpha; } // Update frame of self and moved subnodes @@ -1238,6 +1247,10 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) movedSubnode.frame = [context finalFrameForNode:movedSubnode]; } } completion:^(BOOL finished) { + // Restore all removed subnode alpha values + for (_ASAnimatedTransitionContext *removedSubnodeContext in removedSubnodeContexts) { + removedSubnodeContext.node.alpha = removedSubnodeContext.alpha; + } for (UIView *removedView in removedViews) { [removedView removeFromSuperview]; } @@ -1246,7 +1259,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) }]; } -/* +/** * Hook for subclasses to clean up nodes after the transition happened. Furthermore this can be used from subclasses * to manually perform deletions. */ @@ -1257,9 +1270,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) #pragma mark _ASTransitionContextCompletionDelegate -/* +/** * After completeTransition: is called on the ASContextTransitioning object in animateLayoutTransition: this - * delegate method will be called that start the completion process of the + * delegate method will be called that start the completion process of the transition */ - (void)transitionContext:(_ASTransitionContext *)context didComplete:(BOOL)didComplete { @@ -1267,6 +1280,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) _pendingLayoutTransitionContext = nil; [self _pendingLayoutTransitionDidComplete]; + + // Mark transaction as finished + [self _finishOrCancelTransition]; } #pragma mark - Layout diff --git a/AsyncDisplayKit/_ASTransitionContext.h b/AsyncDisplayKit/_ASTransitionContext.h index 666aed281d..9ea213a8f5 100644 --- a/AsyncDisplayKit/_ASTransitionContext.h +++ b/AsyncDisplayKit/_ASTransitionContext.h @@ -44,3 +44,9 @@ completionDelegate:(id<_ASTransitionContextCompletionDelegate>)completionDelegate; @end + +@interface _ASAnimatedTransitionContext : NSObject +@property (nonatomic, strong, readonly) ASDisplayNode *node; +@property (nonatomic, assign, readonly) CGFloat alpha; ++ (instancetype)contextForNode:(ASDisplayNode *)node alpha:(CGFloat)alphaValue; +@end diff --git a/AsyncDisplayKit/_ASTransitionContext.m b/AsyncDisplayKit/_ASTransitionContext.m index 4ce9554701..30fd1d3983 100644 --- a/AsyncDisplayKit/_ASTransitionContext.m +++ b/AsyncDisplayKit/_ASTransitionContext.m @@ -97,3 +97,21 @@ NSString * const ASTransitionContextToLayoutKey = @"org.asyncdisplaykit.ASTransi } @end + + +@interface _ASAnimatedTransitionContext () +@property (nonatomic, strong, readwrite) ASDisplayNode *node; +@property (nonatomic, assign, readwrite) CGFloat alpha; +@end + +@implementation _ASAnimatedTransitionContext + ++ (instancetype)contextForNode:(ASDisplayNode *)node alpha:(CGFloat)alpha +{ + _ASAnimatedTransitionContext *context = [[_ASAnimatedTransitionContext alloc] init]; + context.node = node; + context.alpha = alpha; + return context; +} + +@end