#import "RNNAnimator.h" #import "RNNTransition.h" @interface RNNAnimator() @property (nonatomic, strong) RNNAnimationOptions* transitionOptions; @property (nonatomic) BOOL backButton; @property (nonatomic, weak) UIViewController* fromVC; @property (nonatomic, weak) UIViewController* toVC; @end @implementation RNNAnimator -(instancetype)initWithTransitionOptions:(RNNAnimationOptions *)transitionOptions { self = [super init]; if (transitionOptions.animations) { [self setupTransition:transitionOptions]; } else { return nil; } return self; } -(void)setupTransition:(RNNAnimationOptions *)transitionOptions { self.transitionOptions = transitionOptions; if (!transitionOptions.animations) { [[NSException exceptionWithName:NSInvalidArgumentException reason:@"No animations" userInfo:nil] raise]; } self.backButton = false; } -(NSArray*)prepareSharedElementTransitionWithComponentView:(UIView*)componentView { NSMutableArray* transitions = [NSMutableArray new]; for (NSDictionary* transition in self.transitionOptions.animations) { RNNTransitionStateHolder* transitionStateHolder = [[RNNTransitionStateHolder alloc] initWithDict:transition]; RNNTransition* transition = [[RNNTransition alloc] initFromVC:self.fromVC toVC:self.toVC transitionOptions:transitionStateHolder isBackButton:self.backButton]; [componentView addSubview:transition.animatedView]; [componentView bringSubviewToFront:transition.animatedView]; [transitions addObject:transition]; } return transitions; } -(void)animateTransitions:(NSArray*)transitions { for (RNNTransition* transition in transitions ) { [transition animate]; } } -(void)animateCompletion:(NSArray*)transitions fromVCSnapshot:(UIView*)fromSnapshot andTransitioningContext:(id)transitionContext { [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:[self.transitionOptions.springDamping doubleValue] initialSpringVelocity:[self.transitionOptions.springVelocity doubleValue] options:UIViewAnimationOptionCurveEaseOut animations:^{ self.toVC.view.alpha = 1; } completion:^(BOOL finished) { for (RNNTransition* transition in transitions ) { [transition transitionCompleted]; } [fromSnapshot removeFromSuperview]; if (![transitionContext transitionWasCancelled]) { self.toVC.view.alpha = 1; [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; self.backButton = true; } }]; } - (NSTimeInterval)transitionDuration:(id )transitionContext { return [self.transitionOptions.duration doubleValue]; } - (void)animateTransition:(id)transitionContext { UIViewController* toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIViewController* fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIView* componentView = [transitionContext containerView]; self.fromVC = fromVC; self.toVC = toVC; toVC.view.frame = fromVC.view.frame; UIView* fromSnapshot = [fromVC.view snapshotViewAfterScreenUpdates:true]; fromSnapshot.frame = fromVC.view.frame; [componentView addSubview:fromSnapshot]; [componentView addSubview:toVC.view]; toVC.view.alpha = 0; NSArray* transitions = [self prepareSharedElementTransitionWithComponentView:componentView]; [self animateCompletion:transitions fromVCSnapshot:fromSnapshot andTransitioningContext:transitionContext]; [self animateTransitions:transitions]; } @end