react-native-navigation的迁移库

RNNAnimator.m 7.3KB

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