Stack navigator component for iOS and Android with animated transitions and gestures
—
Animation timing and easing configuration specifications used to control the duration and feel of screen transitions in stack navigation.
Spring animation configuration that replicates UINavigationController's exact animation behavior on iOS.
/**
* Exact values from UINavigationController's animation configuration
* Uses spring animation with precise iOS timing parameters
*/
const TransitionIOSSpec: TransitionSpec;Configuration Details:
{
animation: 'spring',
config: {
stiffness: 1000,
damping: 500,
mass: 3,
overshootClamping: true,
restDisplacementThreshold: 10,
restSpeedThreshold: 10,
},
}Timing animation configuration for Android activity open transitions on Android Nougat and earlier.
/**
* Configuration for activity open animation from Android Nougat
* Uses timing animation with polynomial easing curve
*/
const FadeInFromBottomAndroidSpec: TransitionSpec;Configuration Details:
{
animation: 'timing',
config: {
duration: 350,
easing: Easing.out(Easing.poly(5)),
},
}Timing animation configuration for Android activity close transitions on Android Nougat and earlier.
/**
* Configuration for activity close animation from Android Nougat
* Uses timing animation with linear easing for quick exit
*/
const FadeOutToBottomAndroidSpec: TransitionSpec;Configuration Details:
{
animation: 'timing',
config: {
duration: 150,
easing: Easing.in(Easing.linear),
},
}Timing animation configuration for Android Pie (API 28) reveal transitions with smooth bezier curve.
/**
* Approximate configuration for activity open animation from Android Pie
* Uses timing animation with custom bezier curve for smooth reveal
*/
const RevealFromBottomAndroidSpec: TransitionSpec;Configuration Details:
{
animation: 'timing',
config: {
duration: 425,
easing: Easing.bezier(0.35, 0.45, 0, 1), // fast_out_extra_slow_in equivalent
},
}Timing animation configuration for Android Q (API 29+) scale transitions with smooth bezier curve.
/**
* Approximate configuration for activity open animation from Android Q
* Uses timing animation with custom bezier curve for scaling effect
*/
const ScaleFromCenterAndroidSpec: TransitionSpec;Configuration Details:
{
animation: 'timing',
config: {
duration: 400,
easing: Easing.bezier(0.35, 0.45, 0, 1), // fast_out_extra_slow_in equivalent
},
}Material Design bottom sheet slide-in animation with accelerate-decelerate interpolator.
/**
* Configuration for bottom sheet slide in animation from Material Design
* Uses timing animation with accelerate-decelerate curve
*/
const BottomSheetSlideInSpec: TransitionSpec;Configuration Details:
{
animation: 'timing',
config: {
duration: 250,
easing: (t) => Math.cos((t + 1) * Math.PI) / 2.0 + 0.5, // AccelerateDecelerateInterpolator
},
}Material Design bottom sheet slide-out animation with accelerate interpolator for quick exit.
/**
* Configuration for bottom sheet slide out animation from Material Design
* Uses timing animation with accelerate curve for quick dismissal
*/
const BottomSheetSlideOutSpec: TransitionSpec;Configuration Details:
{
animation: 'timing',
config: {
duration: 200,
easing: (t) => (t === 1.0 ? 1 : Math.pow(t, 2)), // AccelerateInterpolator
},
}All transition specs conform to the TransitionSpec type:
type TransitionSpec = {
animation: 'spring';
config: Omit<Animated.SpringAnimationConfig, 'toValue' | keyof Animated.AnimationConfig>;
} | {
animation: 'timing';
config: Omit<Animated.TimingAnimationConfig, 'toValue' | keyof Animated.AnimationConfig>;
};import { TransitionSpecs } from '@react-navigation/stack';
// Apply specific timing to screen
<Stack.Screen
name="FastScreen"
component={MyScreen}
options={{
transitionSpec: {
open: TransitionSpecs.FadeInFromBottomAndroidSpec,
close: TransitionSpecs.FadeOutToBottomAndroidSpec,
},
}}
/>
// Apply to all screens in navigator
<Stack.Navigator
screenOptions={{
transitionSpec: {
open: TransitionSpecs.TransitionIOSSpec,
close: TransitionSpecs.TransitionIOSSpec,
},
}}
>import { Easing } from 'react-native';
import type { TransitionSpec } from '@react-navigation/stack';
// Custom spring animation
const CustomSpringSpec: TransitionSpec = {
animation: 'spring',
config: {
stiffness: 800,
damping: 300,
mass: 1,
overshootClamping: false,
restDisplacementThreshold: 0.01,
restSpeedThreshold: 0.01,
},
};
// Custom timing animation
const CustomTimingSpec: TransitionSpec = {
animation: 'timing',
config: {
duration: 300,
easing: Easing.bezier(0.25, 0.1, 0.25, 1), // Material Design curve
},
};
// Apply custom specs
<Stack.Screen
name="CustomAnimation"
component={MyScreen}
options={{
transitionSpec: {
open: CustomSpringSpec,
close: CustomTimingSpec,
},
}}
/>import { Platform } from 'react-native';
import { TransitionSpecs } from '@react-navigation/stack';
const platformTransitionSpec = Platform.select({
ios: {
open: TransitionSpecs.TransitionIOSSpec,
close: TransitionSpecs.TransitionIOSSpec,
},
android: {
open: TransitionSpecs.RevealFromBottomAndroidSpec,
close: TransitionSpecs.FadeOutToBottomAndroidSpec,
},
});
<Stack.Navigator
screenOptions={{
transitionSpec: platformTransitionSpec,
}}
>import { TransitionSpecs } from '@react-navigation/stack';
// Different timing for opening vs closing
<Stack.Screen
name="AsymmetricTiming"
component={MyScreen}
options={{
transitionSpec: {
open: TransitionSpecs.TransitionIOSSpec, // Smooth spring open
close: TransitionSpecs.FadeOutToBottomAndroidSpec, // Quick timing close
},
}}
/>Transition specs work together with card and header interpolators:
import {
TransitionSpecs,
CardStyleInterpolators,
HeaderStyleInterpolators
} from '@react-navigation/stack';
// Complete coordinated animation
<Stack.Screen
name="CoordinatedAnimation"
component={MyScreen}
options={{
transitionSpec: {
open: TransitionSpecs.TransitionIOSSpec,
close: TransitionSpecs.TransitionIOSSpec,
},
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
headerStyleInterpolator: HeaderStyleInterpolators.forUIKit,
}}
/>Install with Tessl CLI
npx tessl i tessl/npm-react-navigation--stack