Skip to content

Commit 178d94d

Browse files
authored
fix(iOS): restore behaviour of RNSScreenStackAnimationNone (#2565)
## Description There is still some header animation noticeable for some reason. <-- This is because we use `fade` transition with duration 0 and do not override interruptible animator! To prevent the animation we could either return `nil` interruptible animator (but overriding the method comes with it's own set of problems, see #2563 and other related) or handle the `none` animation much earlier, when calling `showViewControllers:animated:` in `updateContainer` (pass `animated: NO`). PS: If we would want to pass `animated: NO` I wonder what would happen to dismiss prevention - we implemented it at the stage of the animation start... We need to think this through. Note: Must be implemented with old animation API, because `UIViewPropertyAnimator` does not allow for 0 duration (it uses default if the specified animation duration is below some undocumented treshold). This regression was introduced with #2477 ## Changes We now use old API for `animation: none` & still rely on fade animation to implement it. Note the points made above ☝🏻 - we should refactor this code to make advantage of `animated:` parameter of the `showViewControllers:animated:`. ## Test code and steps to reproduce `TestAnimation` - set stack presentation to `none` - it works as prior to v4. WIP VIDEO ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes
1 parent 6e37c7e commit 178d94d

File tree

3 files changed

+70
-26
lines changed

3 files changed

+70
-26
lines changed

apps/src/tests/TestAnimation.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,18 @@ function Fifth({ navigation }: RoutePropBase<'Fifth'>): React.ReactNode {
7777
);
7878
}
7979

80+
function HeaderRight() {
81+
return (
82+
<Square size={20} color="blue" />
83+
);
84+
}
85+
8086
export default function App() {
8187
return (
8288
<NavigationContainer>
8389
<Stack.Navigator screenOptions={{
8490
fullScreenGestureEnabled: true,
85-
animation: 'simple_push',
86-
//animationMatchesGesture: true,
91+
headerRight: HeaderRight,
8792
}}>
8893
<Stack.Screen name="Home" component={Home} />
8994
<Stack.Screen name="Second" component={Second} options={{

ios/RNSScreenStackAnimator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#pragma once
2+
13
#import "RNSScreen.h"
24

35
@interface RNSScreenStackAnimator : NSObject <UIViewControllerAnimatedTransitioning>

ios/RNSScreenStackAnimator.mm

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)t
5959
}
6060

6161
if (screen != nil && screen.stackAnimation == RNSScreenStackAnimationNone) {
62-
return 0;
62+
return 0.0;
6363
}
6464

6565
if (screen != nil && screen.transitionDuration != nil && [screen.transitionDuration floatValue] >= 0) {
@@ -70,12 +70,6 @@ - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)t
7070
return _transitionDuration;
7171
}
7272

73-
//- (id<UIViewImplicitlyAnimating>)interruptibleAnimatorForTransition:
74-
// (id<UIViewControllerContextTransitioning>)transitionContext
75-
//{
76-
// return _inFlightAnimator;
77-
//}
78-
7973
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
8074
{
8175
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
@@ -489,6 +483,38 @@ - (void)animateWithNoAnimation:(id<UIViewControllerContextTransitioning>)transit
489483
}
490484
}
491485

486+
- (void)animateNoneWithTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext
487+
toVC:(UIViewController *)toViewController
488+
fromVC:(UIViewController *)fromViewController
489+
{
490+
toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];
491+
492+
if (_operation == UINavigationControllerOperationPush) {
493+
[[transitionContext containerView] addSubview:toViewController.view];
494+
toViewController.view.alpha = 0.0;
495+
[UIView animateWithDuration:[self transitionDuration:transitionContext]
496+
animations:^{
497+
toViewController.view.alpha = 1.0;
498+
}
499+
completion:^(BOOL finished) {
500+
toViewController.view.alpha = 1.0;
501+
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
502+
}];
503+
} else if (_operation == UINavigationControllerOperationPop) {
504+
[[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view];
505+
506+
[UIView animateWithDuration:[self transitionDuration:transitionContext]
507+
animations:^{
508+
fromViewController.view.alpha = 0.0;
509+
}
510+
completion:^(BOOL finished) {
511+
fromViewController.view.alpha = 1.0;
512+
513+
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
514+
}];
515+
}
516+
}
517+
492518
#pragma mark - Public API
493519

494520
- (nullable id<UITimingCurveProvider>)timingParamsForAnimationCompletion
@@ -509,24 +535,35 @@ - (void)animateTransitionWithStackAnimation:(RNSScreenStackAnimation)animation
509535
toVC:(UIViewController *)toVC
510536
fromVC:(UIViewController *)fromVC
511537
{
512-
if (animation == RNSScreenStackAnimationSimplePush) {
513-
[self animateSimplePushWithShadowEnabled:shadowEnabled transitionContext:transitionContext toVC:toVC fromVC:fromVC];
514-
return;
515-
} else if (animation == RNSScreenStackAnimationSlideFromLeft) {
516-
[self animateSlideFromLeftWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
517-
return;
518-
} else if (animation == RNSScreenStackAnimationFade || animation == RNSScreenStackAnimationNone) {
519-
[self animateFadeWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
520-
return;
521-
} else if (animation == RNSScreenStackAnimationSlideFromBottom) {
522-
[self animateSlideFromBottomWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
523-
return;
524-
} else if (animation == RNSScreenStackAnimationFadeFromBottom) {
525-
[self animateFadeFromBottomWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
526-
return;
538+
switch (animation) {
539+
case RNSScreenStackAnimationSimplePush:
540+
[self animateSimplePushWithShadowEnabled:shadowEnabled
541+
transitionContext:transitionContext
542+
toVC:toVC
543+
fromVC:fromVC];
544+
return;
545+
case RNSScreenStackAnimationSlideFromLeft:
546+
[self animateSlideFromLeftWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
547+
return;
548+
case RNSScreenStackAnimationFade:
549+
[self animateFadeWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
550+
return;
551+
case RNSScreenStackAnimationSlideFromBottom:
552+
[self animateSlideFromBottomWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
553+
return;
554+
case RNSScreenStackAnimationFadeFromBottom:
555+
[self animateFadeFromBottomWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
556+
return;
557+
case RNSScreenStackAnimationNone:
558+
[self animateNoneWithTransitionContext:transitionContext toVC:toVC fromVC:fromVC];
559+
return;
560+
default:
561+
// simple_push is the default custom animation
562+
[self animateSimplePushWithShadowEnabled:shadowEnabled
563+
transitionContext:transitionContext
564+
toVC:toVC
565+
fromVC:fromVC];
527566
}
528-
// simple_push is the default custom animation
529-
[self animateSimplePushWithShadowEnabled:shadowEnabled transitionContext:transitionContext toVC:toVC fromVC:fromVC];
530567
}
531568

532569
+ (UISpringTimingParameters *)defaultSpringTimingParametersApprox

0 commit comments

Comments
 (0)