LOTAnimationTransitionController.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //
  2. // LOTAnimationTransitionController.m
  3. // Lottie
  4. //
  5. // Created by Brandon Withrow on 1/18/17.
  6. // Copyright © 2017 Brandon Withrow. All rights reserved.
  7. //
  8. #import "LOTAnimationTransitionController.h"
  9. #import "LOTAnimationView.h"
  10. @implementation LOTAnimationTransitionController {
  11. LOTAnimationView *transitionAnimationView_;
  12. NSString *fromLayerName_;
  13. NSString *toLayerName_;
  14. NSBundle *inBundle_;
  15. BOOL _applyTransform;
  16. }
  17. - (nonnull instancetype)initWithAnimationNamed:(nonnull NSString *)animation
  18. fromLayerNamed:(nullable NSString *)fromLayer
  19. toLayerNamed:(nullable NSString *)toLayer
  20. applyAnimationTransform:(BOOL)applyAnimationTransform {
  21. return [self initWithAnimationNamed:animation
  22. fromLayerNamed:fromLayer
  23. toLayerNamed:toLayer
  24. applyAnimationTransform:applyAnimationTransform
  25. inBundle:[NSBundle mainBundle]];
  26. }
  27. - (instancetype)initWithAnimationNamed:(NSString *)animation
  28. fromLayerNamed:(NSString *)fromLayer
  29. toLayerNamed:(NSString *)toLayer
  30. applyAnimationTransform:(BOOL)applyAnimationTransform
  31. inBundle:(NSBundle *)bundle {
  32. self = [super init];
  33. if (self) {
  34. transitionAnimationView_ = [LOTAnimationView animationNamed:animation inBundle:bundle];
  35. fromLayerName_ = fromLayer;
  36. toLayerName_ = toLayer;
  37. _applyTransform = applyAnimationTransform;
  38. }
  39. return self;
  40. }
  41. - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
  42. return transitionAnimationView_.animationDuration;
  43. }
  44. - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
  45. UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  46. UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
  47. UIView *containerView = transitionContext.containerView;
  48. UIView *toSnapshot = [toVC.view resizableSnapshotViewFromRect:containerView.bounds
  49. afterScreenUpdates:YES
  50. withCapInsets:UIEdgeInsetsZero];
  51. toSnapshot.frame = containerView.bounds;
  52. UIView *fromSnapshot = [fromVC.view resizableSnapshotViewFromRect:containerView.bounds
  53. afterScreenUpdates:NO
  54. withCapInsets:UIEdgeInsetsZero];
  55. fromSnapshot.frame = containerView.bounds;
  56. transitionAnimationView_.frame = containerView.bounds;
  57. transitionAnimationView_.contentMode = UIViewContentModeScaleAspectFill;
  58. [containerView addSubview:transitionAnimationView_];
  59. BOOL crossFadeViews = NO;
  60. if (toLayerName_.length) {
  61. LOTKeypath *toKeypath = [LOTKeypath keypathWithString:toLayerName_];
  62. CGRect convertedBounds = [transitionAnimationView_ convertRect:containerView.bounds toKeypathLayer:toKeypath];
  63. toSnapshot.frame = convertedBounds;
  64. if (_applyTransform) {
  65. [transitionAnimationView_ addSubview:toSnapshot toKeypathLayer:toKeypath];
  66. } else {
  67. [transitionAnimationView_ maskSubview:toSnapshot toKeypathLayer:toKeypath];
  68. }
  69. } else {
  70. [containerView addSubview:toSnapshot];
  71. [containerView sendSubviewToBack:toSnapshot];
  72. toSnapshot.alpha = 0;
  73. crossFadeViews = YES;
  74. }
  75. if (fromLayerName_.length) {
  76. LOTKeypath *fromKeypath = [LOTKeypath keypathWithString:fromLayerName_];
  77. CGRect convertedBounds = [transitionAnimationView_ convertRect:containerView.bounds fromKeypathLayer:fromKeypath];
  78. fromSnapshot.frame = convertedBounds;
  79. if (_applyTransform) {
  80. [transitionAnimationView_ addSubview:fromSnapshot toKeypathLayer:fromKeypath];
  81. } else {
  82. [transitionAnimationView_ maskSubview:fromSnapshot toKeypathLayer:fromKeypath];
  83. }
  84. } else {
  85. [containerView addSubview:fromSnapshot];
  86. [containerView sendSubviewToBack:fromSnapshot];
  87. }
  88. [containerView addSubview:toVC.view];
  89. toVC.view.hidden = YES;
  90. if (crossFadeViews) {
  91. CGFloat duration = transitionAnimationView_.animationDuration * 0.25;
  92. CGFloat delay = (transitionAnimationView_.animationDuration - duration) / 2.f;
  93. [UIView animateWithDuration:duration
  94. delay:delay
  95. options:(UIViewAnimationOptionCurveEaseInOut)
  96. animations:^{
  97. toSnapshot.alpha = 1;
  98. } completion:^(BOOL finished) {
  99. }];
  100. }
  101. [transitionAnimationView_ playWithCompletion:^(BOOL animationFinished) {
  102. toVC.view.hidden = false;
  103. [self->transitionAnimationView_ removeFromSuperview];
  104. [transitionContext completeTransition:animationFinished];
  105. }];
  106. }
  107. @end