Skip to content

Commit

Permalink
fix(iOS): shadow does not appear on manual transition during push and…
Browse files Browse the repository at this point in the history
… pop
  • Loading branch information
maksg committed Jul 8, 2024
1 parent ab065f2 commit 34420b2
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions apps/test-examples/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import Test2069 from './src/Test2069';
import Test2118 from './src/Test2118';
import Test2184 from './src/Test2184';
import Test2223 from './src/Test2223';
import Test2227 from './src/Test2227';
import Test2229 from './src/Test2229';
import TestScreenAnimation from './src/TestScreenAnimation';
import TestHeader from './src/TestHeader';
Expand Down
57 changes: 57 additions & 0 deletions apps/test-examples/src/Test2227.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {
createNativeStackNavigator,
NativeStackScreenProps,
} from '@react-navigation/native-stack';
import {Button, View, Text} from 'react-native';

type RootStackParamList = {
Home: undefined;
Details: undefined;
};

type HomeScreenProps = NativeStackScreenProps<RootStackParamList, 'Home'>;
type DetailsScreenProps = NativeStackScreenProps<RootStackParamList, 'Details'>;

const Stack = createNativeStackNavigator<RootStackParamList>();

function HomeScreen({navigation}: HomeScreenProps) {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}

function DetailsScreen({navigation}: DetailsScreenProps) {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Details Screen</Text>
<Button
title="Go to Details Again"
onPress={() => navigation.push('Details')}
/>
<Button title="Go Back" onPress={() => navigation.goBack()} />
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
);
}

export default function App() {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
fullScreenGestureEnabled: true,
}}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
1 change: 1 addition & 0 deletions ios/RNSScreenStack.mm
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@ - (void)handleSwipe:(UIPanGestureRecognizer *)gestureRecognizer
[_interactionController cancelInteractiveTransition];
}
_interactionController = nil;
_isFullWidthSwiping = NO;
}
default: {
break;
Expand Down
15 changes: 15 additions & 0 deletions ios/RNSScreenStackAnimator.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
static const float RNSSlideCloseTransitionDurationProportion = 0.25 / 0.35;
static const float RNSFadeCloseTransitionDurationProportion = 0.15 / 0.35;
static const float RNSFadeCloseDelayTransitionDurationProportion = 0.1 / 0.35;
// same value is used in other projects using similar approach for transistions
// and it looks the most similar to the value used by Apple
constexpr float RNSShadowViewMaxAlpha = 0.1;

@implementation RNSScreenStackAnimator {
UINavigationControllerOperation _operation;
Expand Down Expand Up @@ -105,28 +108,40 @@ - (void)animateSimplePushWithTransitionContext:(id<UIViewControllerContextTransi
leftTransform = CGAffineTransformMakeTranslation(belowViewWidth, 0);
}

auto shadowView = [[UIView alloc] initWithFrame:fromViewController.view.frame];
shadowView.backgroundColor = [UIColor blackColor];

if (_operation == UINavigationControllerOperationPush) {
toViewController.view.transform = rightTransform;
[[transitionContext containerView] addSubview:toViewController.view];
[[transitionContext containerView] insertSubview:shadowView belowSubview:toViewController.view];
shadowView.alpha = 0.0;

[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
fromViewController.view.transform = leftTransform;
toViewController.view.transform = CGAffineTransformIdentity;
shadowView.alpha = RNSShadowViewMaxAlpha;
}
completion:^(BOOL finished) {
[shadowView removeFromSuperview];
fromViewController.view.transform = CGAffineTransformIdentity;
toViewController.view.transform = CGAffineTransformIdentity;
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
} else if (_operation == UINavigationControllerOperationPop) {
toViewController.view.transform = leftTransform;
[[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view];
[[transitionContext containerView] insertSubview:shadowView belowSubview:fromViewController.view];
shadowView.alpha = RNSShadowViewMaxAlpha;

void (^animationBlock)(void) = ^{
toViewController.view.transform = CGAffineTransformIdentity;
fromViewController.view.transform = rightTransform;
shadowView.alpha = 0.0;
};
void (^completionBlock)(BOOL) = ^(BOOL finished) {
[shadowView removeFromSuperview];
fromViewController.view.transform = CGAffineTransformIdentity;
toViewController.view.transform = CGAffineTransformIdentity;
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
Expand Down

0 comments on commit 34420b2

Please sign in to comment.