mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-26 09:14:22 +08:00
fix: use next screen's animation when not focused
This commit is contained in:
@@ -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';
|
||||
@@ -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,
|
||||
|
||||
72
packages/stack/example/src/PerScreenTransitions.tsx
Normal file
72
packages/stack/example/src/PerScreenTransitions.tsx
Normal file
@@ -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,
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -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]
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user