react-native-navigation的迁移库

RNNAnimator.m 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #import <React/RCTRedBox.h>
  2. #import "RNNAnimator.h"
  3. #import "RNNElementView.h"
  4. #import "RNNInteractivePopAnimator.h"
  5. #import "VICMAImageView.h"
  6. #import "RNNTransitionStateHolder.h"
  7. #import "RNNElementFinder.h"
  8. #import "RNNViewLocation.h"
  9. #import "RNNAnimatedView.h"
  10. @interface RNNAnimator()
  11. @property (nonatomic, strong) RNNTransitionOptions* transitionOptions;
  12. @property (nonatomic, strong) RNNInteractivePopAnimator* interactivePopAnimator;
  13. @property (nonatomic) BOOL backButton;
  14. @property (nonatomic, strong) UIViewController* fromVC;
  15. @property (nonatomic, strong) UIViewController* toVC;
  16. @end
  17. @implementation RNNAnimator
  18. -(instancetype)initWithTransitionOptions:(RNNTransitionOptions *)transitionOptions {
  19. self = [super init];
  20. if (transitionOptions) {
  21. [self setupTransition:transitionOptions];
  22. } else {
  23. return nil;
  24. }
  25. return self;
  26. }
  27. -(void)setupTransition:(RNNTransitionOptions *)transitionOptions {
  28. self.transitionOptions = transitionOptions;
  29. if (!transitionOptions.animations) {
  30. [[NSException exceptionWithName:NSInvalidArgumentException reason:@"No animations" userInfo:nil] raise];
  31. }
  32. self.backButton = false;
  33. }
  34. -(NSArray*)prepareSharedElementTransition:(NSArray*)RNNSharedElementsToVC
  35. andfromVCElements:(NSArray*)RNNSharedElementsFromVC
  36. withComponentView:(UIView*)componentView {
  37. NSMutableArray* transitions = [NSMutableArray new];
  38. for (NSDictionary* transition in self.transitionOptions.animations) {
  39. RNNTransitionStateHolder* transitionStateHolder = [[RNNTransitionStateHolder alloc] initWithTransition:transition];
  40. RNNElementFinder* elementFinder = [[RNNElementFinder alloc] initWithToVC:self.toVC andfromVC:self.fromVC];
  41. [elementFinder findElementsInTransition:transitionStateHolder];
  42. RNNViewLocation* animatedViewLocations = [[RNNViewLocation alloc] initWithTransition:transitionStateHolder andVC:self.fromVC];
  43. RNNAnimatedView* animatedView = [[RNNAnimatedView alloc] initWithTransition:transitionStateHolder andLocation:animatedViewLocations andIsBackButton:self.backButton];
  44. transitionStateHolder.locations = animatedViewLocations;
  45. [componentView addSubview:animatedView];
  46. [componentView bringSubviewToFront:animatedView];
  47. transitionStateHolder.animatedView = animatedView;
  48. [transitions addObject:transitionStateHolder];
  49. if (transitionStateHolder.isSharedElementTransition) {
  50. [transitionStateHolder.toElement setHidden: YES];
  51. }
  52. [transitionStateHolder.fromElement setHidden:YES];
  53. }
  54. return transitions;
  55. }
  56. -(void)animateTransitions:(NSArray*)transitions {
  57. for (RNNTransitionStateHolder* transition in transitions ) {
  58. [UIView animateWithDuration:transition.duration delay:transition.startDelay usingSpringWithDamping:transition.springDamping initialSpringVelocity:transition.springVelocity options:UIViewAnimationOptionCurveEaseOut animations:^{
  59. RNNAnimatedView* animatedView = transition.animatedView;
  60. if (!self.backButton) {
  61. [self setAnimatedViewFinalProperties:animatedView toElement:transition.toElement fromElement:transition.fromElement isSharedElementTransition:transition.isSharedElementTransition withTransform:transition.locations.transform withCenter:transition.locations.toCenter andAlpha:transition.endAlpha];
  62. } else {
  63. [self setAnimatedViewFinalProperties:animatedView toElement:transition.fromElement fromElement:transition.fromElement isSharedElementTransition:transition.isSharedElementTransition withTransform:transition.locations.transformBack withCenter:transition.locations.fromCenter andAlpha:transition.startAlpha];
  64. }
  65. } completion:^(BOOL finished) {
  66. }];
  67. }
  68. }
  69. -(void)setAnimatedViewFinalProperties:(RNNAnimatedView*)animatedView toElement:(RNNElementView*)toElement fromElement:(RNNElementView*)fromElement isSharedElementTransition:(BOOL)isShared withTransform:(CGAffineTransform)transform withCenter:(CGPoint)center andAlpha:(double)alpha {
  70. animatedView.alpha = alpha;
  71. animatedView.center = center;
  72. animatedView.transform = transform;
  73. if (isShared) {
  74. if ([[fromElement subviews][0] isKindOfClass:[UIImageView class]]) {
  75. animatedView.contentMode = UIViewContentModeScaleAspectFill;
  76. if ([toElement resizeMode]){
  77. animatedView.contentMode = [RNNAnimatedView contentModefromString:[toElement resizeMode]];
  78. }
  79. }
  80. }
  81. }
  82. -(void)animateComplition:(NSArray*)transitions fromVCSnapshot:(UIView*)fromSnapshot andTransitioningContext:(id<UIViewControllerContextTransitioning>)transitionContext {
  83. [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:[self.transitionOptions.springDamping doubleValue] initialSpringVelocity:[self.transitionOptions.springVelocity doubleValue] options:UIViewAnimationOptionCurveEaseOut animations:^{
  84. self.toVC.view.alpha = 1;
  85. } completion:^(BOOL finished) {
  86. for (RNNTransitionStateHolder* transition in transitions ) {
  87. [transition.fromElement setHidden:NO];
  88. if (transition.isSharedElementTransition) {
  89. [transition.toElement setHidden:NO];
  90. }
  91. RNNAnimatedView* animtedView = transition.animatedView;
  92. [animtedView removeFromSuperview];
  93. if (transition.interactivePop) {
  94. self.interactivePopAnimator = [[RNNInteractivePopAnimator alloc] initWithTopView:transition.toElement andBottomView:transition.fromElement andOriginFrame:transition.locations.fromFrame andViewController:self.toVC];
  95. UIPanGestureRecognizer* gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopAnimator
  96. action:@selector(handleGesture:)];
  97. [transition.toElement addGestureRecognizer:gesture];
  98. }
  99. }
  100. [fromSnapshot removeFromSuperview];
  101. if (![transitionContext transitionWasCancelled]) {
  102. self.toVC.view.alpha = 1;
  103. [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
  104. self.backButton = true;
  105. }
  106. }];
  107. }
  108. - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
  109. return [self.transitionOptions.duration doubleValue];
  110. }
  111. - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
  112. UIViewController* toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
  113. UIViewController* fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  114. UIView* componentView = [transitionContext containerView];
  115. self.fromVC = fromVC;
  116. self.toVC = toVC;
  117. toVC.view.frame = fromVC.view.frame;
  118. UIView* fromSnapshot = [fromVC.view snapshotViewAfterScreenUpdates:true];
  119. fromSnapshot.frame = fromVC.view.frame;
  120. [componentView addSubview:fromSnapshot];
  121. [componentView addSubview:toVC.view];
  122. toVC.view.alpha = 0;
  123. NSArray* onlyForTesting = @[];
  124. NSArray* onlyForTesting2 = @[];
  125. NSArray* transitions = [self prepareSharedElementTransition:onlyForTesting andfromVCElements:onlyForTesting2 withComponentView:componentView];
  126. [self animateComplition:transitions fromVCSnapshot:fromSnapshot andTransitioningContext:transitionContext];
  127. [self animateTransitions:transitions];
  128. }
  129. @end