Skip to content
This repository has been archived by the owner on Feb 25, 2020. It is now read-only.

Commit

Permalink
fix: use next screen's animation when not focused
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 committed Oct 6, 2019
1 parent fd3f0bd commit 8f3c665
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 5 deletions.
6 changes: 6 additions & 0 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import ImageStack from './src/ImageStack';
import TransparentStack from './src/TransparentStack';
import ModalStack from './src/ModalStack';
import ModalPresentation from './src/ModalPresentation';
import PerScreenTransitions from './src/PerScreenTransitions';
import LifecycleInteraction from './src/LifecycleInteraction';
import GestureInteraction from './src/GestureInteraction';
import SwitchWithStacks from './src/SwitchWithStacks';
Expand Down Expand Up @@ -57,6 +58,11 @@ const data: Item[] = [
title: 'Modal (iOS style)',
routeName: 'ModalPresentation',
},
{
component: PerScreenTransitions,
title: 'Per screen transitions',
routeName: 'PerScreenTransitions',
},
{ component: FullScreen, title: 'Full Screen', routeName: 'FullScreen' },
{
component: LifecycleInteraction,
Expand Down
72 changes: 72 additions & 0 deletions example/src/PerScreenTransitions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import {
createStackNavigator,
TransitionPresets,
NavigationStackScreenProps,
} from 'react-navigation-stack';

function SlideScreen({ navigation }: NavigationStackScreenProps) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Slide Screen</Text>
<Button title="Go to Modal" onPress={() => navigation.push('Modal')} />
<Button title="Go to Reveal" onPress={() => navigation.push('Reveal')} />
<Button
title="Go back to all examples"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}

function ModalScreen({ navigation }: NavigationStackScreenProps) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Slide Screen</Text>
<Button title="Go to Reveal" onPress={() => navigation.push('Reveal')} />
<Button title="Go to Slide" onPress={() => navigation.push('Slide')} />
<Button
title="Go back to all examples"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}

function RevealScreen({ navigation }: NavigationStackScreenProps) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Slide Screen</Text>
<Button title="Go to Slide" onPress={() => navigation.push('Slide')} />
<Button title="Go to Modal" onPress={() => navigation.push('Modal')} />
<Button
title="Go back to all examples"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}

export default createStackNavigator(
{
Slide: {
screen: SlideScreen,
navigationOptions: TransitionPresets.SlideFromRightIOS,
},
Modal: {
screen: ModalScreen,
navigationOptions: TransitionPresets.ModalSlideFromBottomIOS,
},
Reveal: {
screen: RevealScreen,
navigationOptions: TransitionPresets.RevealFromBottomAndroid,
},
},
{
defaultNavigationOptions: {
cardOverlayEnabled: true,
gestureEnabled: true,
},
}
);
42 changes: 37 additions & 5 deletions src/views/Stack/Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ export default class Stack extends React.Component<Props, State> {
{routes.map((route, index, self) => {
const focused = focusedRoute.key === route.key;
const current = progress[route.key];
const descriptor = descriptors[route.key];
const scene = scenes[index];
const next = self[index + 1]
? progress[self[index + 1].key]
Expand Down Expand Up @@ -358,10 +357,42 @@ export default class Stack extends React.Component<Props, State> {
cardStyleInterpolator = defaultTransitionPreset.cardStyleInterpolator,
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
gestureVelocityImpact,
} = descriptor
? descriptor.options
} = scene.descriptor
? scene.descriptor.options
: ({} as NavigationStackOptions);

let transitionConfig = {
transitionSpec,
cardStyleInterpolator,
headerStyleInterpolator,
};

// When a screen is not the last, it should use next screen's transition config
// Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
// For example combining a slide and a modal transition would look wrong otherwise
// With this approach, combining different transition styles in the same navigator mostly looks right
// This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
// but majority of the transitions look alright
if (index !== self.length - 1) {
const nextScene = scenes[index + 1];

if (nextScene) {
const {
transitionSpec = defaultTransitionPreset.transitionSpec,
cardStyleInterpolator = defaultTransitionPreset.cardStyleInterpolator,
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
} = nextScene.descriptor
? nextScene.descriptor.options
: ({} as NavigationStackOptions);

transitionConfig = {
transitionSpec,
cardStyleInterpolator,
headerStyleInterpolator,
};
}
}

return (
<MaybeScreen
key={route.key}
Expand All @@ -384,11 +415,9 @@ export default class Stack extends React.Component<Props, State> {
cardOverlayEnabled={cardOverlayEnabled}
cardShadowEnabled={cardShadowEnabled}
cardStyle={cardStyle}
gestureEnabled={index !== 0 && getGesturesEnabled({ route })}
onPageChangeStart={onPageChangeStart}
onPageChangeConfirm={onPageChangeConfirm}
onPageChangeCancel={onPageChangeCancel}
gestureResponseDistance={gestureResponseDistance}
floatingHeaderHeight={floatingHeaderHeights[route.key]}
hasCustomHeader={header === null}
getPreviousRoute={getPreviousRoute}
Expand All @@ -405,7 +434,10 @@ export default class Stack extends React.Component<Props, State> {
transitionSpec={transitionSpec}
cardStyleInterpolator={cardStyleInterpolator}
headerStyleInterpolator={headerStyleInterpolator}
gestureEnabled={index !== 0 && getGesturesEnabled({ route })}
gestureResponseDistance={gestureResponseDistance}
gestureVelocityImpact={gestureVelocityImpact}
{...transitionConfig}
/>
</MaybeScreen>
);
Expand Down

0 comments on commit 8f3c665

Please sign in to comment.